Bash

在連續命令中將文件名作為單獨的參數維護

  • December 20, 2018

免責聲明:這與 ls 或 grep 等特定命令無關,儘管我在範例中使用它們,但這更像是 bash 的事情。

假設我想查看所有包含“某個單詞”的一組文件 (ls -l) 的文件大小、時間戳和權限/所有者/組。通常我會這樣做:

ls -l $( grep -l 'a certain word' * )

這就像魔術一樣,直到任何文件名都包含一個空格,比如一個名為“文件名”的文件。然後ls找不到它認為是兩個文件名,“文件”和“名稱”。

Bash 腳本有一種熟悉的方法來解決這個問題的變體,如果你在命令行中將文件名傳遞給腳本,它們被引用為 $ {1}, $ {2} 等。如果您將它們用引號括起來,即“ $ {1}", " $ {2}”,那麼如果它們有空格,您就沒有問題,您甚至可以使用“${@}”一次處理所有文件名,這將正確列出每個參數,並保持它們完整如果他們有空格 - 我只是沒有找到我上面列出的 grep/ls 樣式問題的這種機制。如果你包裝擴展命令,$( )用引號將所有文件視為 ls 的一個大參數。

我通常用類似的東西來解決它grep -l .... | while read file; do ls -l "${file}"; done,但我真的不應該這樣做。並且這樣做仍然不允許按日期/大小/等對文件進行排序(即ls -ltr $( grep -l ....)

我一直認為 bash 對此有一個解決方案,但我還沒有遇到它,這個問題只是偶爾出現一次,我通常會解決它,但它現在已經困擾了我很多,我認為一定有辦法。

是的,我已經看到了以下內容,它們要麼是由正在使用的特定工具(如 tar)解決的問題,要麼是“抱歉,你不能從這裡到達那裡”,因為他們的問題是特定於命令的. 我要求處理作為結果作為參數傳遞給另一個命令的任何嵌入空間的文件名,而不是更多時間或找到解決此問題的魔法。我寧願這個問題沒有答案(證明沒有解決方案),而不是提供任何不一樣的問題:

唔。@don_crissti 已經在評論中給出了grep的答案。但既然你說它不是真的grepor ls,我將重寫有問題的命令以不使用這些命令。

我想你想要的是:

do-something-with $(produce-list-of-files)

其中一個命令的輸出應作為命令行參數放入另一個命令。恰好有一個實用程序,它被稱為xargs (man page)

如果文件名“不錯”,我們可以這樣做

produce-list-of-files | xargs do-something-with

如果文件名可以包含空格但用換行符分隔,我們必須告訴xargs不要拆分任何空格,而只能拆分換行符:

produce-list-of-files | xargs -d '\n' do-something-with

如果文件名也可以包含換行符,則列表必須由 NUL 分隔(’\0’,值為零的字節),我們需要一個xargs支持它的。至少某些版本的各種實用程序支持列出由 NUL 分隔的文件,而不是換行符,這些工具的 GNU 版本中至少有find -print0,sort -zgrep -Z。在xargs標誌是--null-0。所以:

produce-list-of-files -0 | xargs -0 do-something-with

cat一個使用and執行的範例ls -l

$ touch "abba acdc" "foo bar" $'new\nline'
$ echo -en "abba acdc\0foo bar\0new\nline\0" > list
$ cat list | xargs -0 ls -l
-rw-r--r-- 1 itvirta itvirta 0 Aug  2 01:23 abba acdc
-rw-r--r-- 1 itvirta itvirta 0 Aug  2 01:23 foo bar
-rw-r--r-- 1 itvirta itvirta 0 Aug  2 01:23 new?line

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