如何將人類可讀路徑清單重新導向到另一個命令?

如何將人類可讀路徑清單重新導向到另一個命令?

當使用命令的輸出時,例如locate以「人類可讀形式」產生路徑列表(即\前面沒有空格)的命令的輸出,如何將它們的輸出重新導向到另一個命令?

的輸出$ locate [something]會產生其中包含空格的路徑,這將禁止其他程式使用包含空格的路徑。例如,如果我要

$ du -h `locate *.doc`

這將對包含空格的所有檔案和目錄產生錯誤。 (將刻度線包裹在空格中不起作用)

答案1

您使用的具體原因是什麼locate?這似乎符合您的要求:

find . -type f -name '*doc' -exec du -h "{}" \;

也就是說,如果你真的locate如果確實想要使用像or 這樣的工具find並將其輸入作為參數傳遞給另一個程序,您可以利用NUL某些工具提供的分隔輸出和輸入。 locate並且find兩者都有一個選項(locate's-0find's -print0),這將允許您獲得更編程友好的輸出,其xargs設計用於讀取它是 -0爭論:

find . -type f -name '*doc' -print0 | xargs -0 du -h

locate -0 '*doc' | xargs -0 du -h

答案2

如果您想要/需要將同一行傳遞給多個命令,則可以使用以下方法:

#!/usr/bin/env bash

T="${IFS}" # Save off the Internal Field Separator

IFS=$'\n' # Set it to newline.

while read file_line
do
        echo "--"
        echo "${file_line}"
        echo "--"
done <<< $(locate $1) 
IFS="${T}  # Set it back to the original IFS. 

包裹起來是個好主意任何“”中可能有空格的變數。

答案3

不加引號的命令替換($(...)`...`古老的形式)會在類似 Bourne 的 shell 中呼叫 split+glob(僅在 zsh 中分割)。

預設情況下,分割是針對$IFS包含空格、製表符和換行符(以及 zsh 中的 NUL)的特殊參數的字元完成的,這解釋了為什麼您的命令不適用於包含空格字元的檔案名稱。

你可以這樣做:

(IFS='
' # split on newline only
set -o noglob # disable glob
du -hc -- $(locate '*.doc'))

但如果檔案名稱包含換行符,這仍然會失敗。的輸出locate根本無法進行後處理。

大多數locate實作都有一個-0選項來輸出檔案路徑NUL- 分隔。 NUL 是唯一不能出現在檔案路徑中的位元組值,這表示輸出是可後處理的。您只需要按 NUL 進行拆分即可。

zsh

IFS=$'\0'
du -hc -- $(locate -0 '*.doc')

或者,更好的是,使用顯式 split-on-NUL 運算子:

du -hc -- ${(0)"$(locate -0 '*.doc')"}

bash4.4+ 中,可能是:

readarray -td '' files < <(locate -0 '*.doc')
du -hc -- "${files[@]}"

這仍然留下兩個問題:

  1. 如果locate找不到任何文件,du -hc --將不帶參數運行,這意味著它將為您提供當前工作目錄的磁碟使用情況。
  2. 另一方面,如果locate找到許多文件,您可能最終會達到系統呼叫的限制execve()並獲得一個arg 列表太長錯誤。

透過執行以下操作可以避免這兩個問題:

locate -0 '*.doc' | xargs -r0 du -hc --

-r並且-0是來自 GNU 實現的非標準擴展,xargs就像-h是來自 GNU 實現的非標準擴展du)。

然而,這引入了一個新問題:xargs將運行du多次來解決execve()限制,但這意味著您將得到幾total行,並且多次硬連結的檔案的磁碟使用情況可能最終會被計算多次。

感謝-r,如果找不到任何文件,則du不會運行,但這也意味著您不會得到一行。locate0 total

使用最新版本的 GNU du,可以透過以下方式解決這些問題:

locate -0 '*.doc' | du --files0-from=- -hc

這次,文件列表是透過管道而不是參數傳遞的,因此參數的大小沒有限制。這也意味著不需要分配大量記憶體來儲存該列表,du一旦locate開始輸出它就可以開始處理它。

相關內容