Filesystems

如何正確使用tail連接所有隱藏文件

  • June 24, 2021

問題

我希望能夠:

  1. 連接目錄中的所有文件(正常和隱藏),
  2. 但我也想在每個連接的開頭顯示每個文件的標題。

我在網上找到了一些解決方案,我可以用tail -n +1 * 2>/dev/null超級巧妙的技巧來做#2,但它不包括隱藏文件,就像我要做的那樣:cat * .* 2>/dev/null 甚至head * .* 2>/dev/null

cat 命令可以解決問題,但不包含文件名,head 命令不會列印/連接每個文件的全部內容。

問題

有沒有辦法做我需要做的事情tail如果不是什麼是實現相同結果/輸出的好替代品。

更新一個例子

嘗試連接所有文件(正常和隱藏)時的 tail 命令


[kevin@PC-Fedora tmp]$ ls -la
total 8
drwx------   2 user user 4096 Jun 23 09:24 .
drwxr-xr-x. 54 user user 4096 Jun 23 08:21 ..
-rw-rw-r--   1 user user    0 Jun 23 09:24 .f1
-rw-rw-r--   1 user user    0 Jun 23 09:24 f1
-rw-rw-r--   1 user user    0 Jun 23 09:24 .f2
-rw-rw-r--   1 user user    0 Jun 23 09:24 f2
-rw-rw-r--   1 user user    0 Jun 23 09:24 .f3
-rw-rw-r--   1 user user    0 Jun 23 09:24 f3
-rw-rw-r--   1 user user    0 Jun 23 09:24 .f4
-rw-rw-r--   1 user user    0 Jun 23 09:24 f4
-rw-rw-r--   1 user user    0 Jun 23 09:24 f5
[user@PC-Fedora tmp]$ tail -n +1 *
==> f1 <==

==> f2 <==

==> f3 <==

==> f4 <==

==> f5 <==
[user@PC-Fedora tmp]$ tail -n +1 * .*
==> f1 <==

==> f2 <==

==> f3 <==

==> f4 <==

==> f5 <==

==> . <==
tail: error reading '.': Is a directory
[user@PC-Fedora tmp]$ 

使用zsh和 GNU tail(並非所有尾部實現都可以採用多個文件名參數,並且並非所有實現都會顯示文件名):

() { (($# == 0)) || tail -vn +1 -- "$@" < /dev/null; } *(ND)

-v即使只有一個文件,D對於dotglob,N對於nullglob,仍然使用匿名函式列印文件名,該函式傳遞該glob的擴展並檢查目前目錄為空的特殊情況。

</dev/null``tail是為了部分減輕 GNU在傳遞名為 的文件名-時將讀取 stdin的事實。在這裡,我們只是阻止它讀取標準輸入,但它仍然不會讀取名為-. 另一種方法是使用"${@/#%-/./-}"代替"$@"替換-./-,但這也意味著您會看到文件而==> ./- <==不是文件(仍然可能比 更好)。==> - <==``-``==> standard input <==

您可能還想添加.(or -.) glob 限定符以限制正常文件,以避免錯誤或更糟,如果目前目錄 ( *(ND-.)) 中有目錄或其他類型的非正常文件。

ksh93GNU相同tail

(
 FIGNORE='@(.|..)'
 set -- ~(N)*
 (($# == 0)) || tail -vn +1 -- "$@" < /dev/null
)

bashGNU相同tail

(
 setopt -s nullglob dotglob
 set -- *
 (($# == 0)) || tail -vn +1 -- "$@" < /dev/null
)

或者使用 GNUtail和任何 POSIX sh(包括zsh,但僅在sh仿真中),也限制為正常文件或對正常文件的符號連結並替換-./-,但可能以不同的順序處理文件,因為我們在.*其他文件之前執行這些文件:

(
 set --
 for file in .* *
   [ -f "$file" ] || continue
   [ "$file" = - ] && file=./-
   set -- "$@" "$file"
 done
 [ "$#" -eq 0 ] || exec tail -n +1 -- "$@"
)

或者您可以使用 GNU awk(此處為zsh):

() {
 (( $# == 0 )) ||
   gawk 'BEGINFILE{
           print sep "==> "substr(FILENAME, 3)" <=="
           sep = "\n"
         }
         {print}' "$@"
} *(ND-.)

awk``tail-包含=. _ 我們通過添加./我們在顯示時剝離的前綴來解決這兩個問題。請注意,如果文件末尾缺少,awk 會添加一個換行符。

或使用循環:

sep=
for f (*(ND-.)) {
 print -r "$sep==> $f <=="
 sep=$'\n'
 cat < $f
}

cat與 有同樣的問題-,我們通過在標準輸入上傳遞文件而不是參數來解決這個問題)

引用自:https://unix.stackexchange.com/questions/655511