Shell-Script

使用 xargs 輸入替換命令

  • April 5, 2022

我正在嘗試編寫一個簡單的命令,該命令將為特定目錄中的所有文件創建符號連結(是的,完全一樣,lndir但我不能使用它,所以我嘗試模仿它)。

find我使用+嘗試了以下操作xargs

find $(realpath ${FROM_DIR}) -maxdepth 1 -print0 | xargs -0 -I{} ln -sfn {} ${TO_DIR}/$(basename {})

但問題是 shell $(basename {})在執行該行之前替換了一次,而不是每個參數。

將其編寫為循環如下所示:

for i in $(find $(realpath ${FROM_DIR}) -maxdepth 1)
do
   ln -sfn $i ${TO_DIR}/$(basename $i)
done

這有效,但速度相對較慢。我想知道這是否也可以使用xargs

聽起來像你想要的:

ln -sf -- "$(realpath -- "$FROM_DIR")"/* "$TO_DIR/"

當最後一個參數是一個目錄時,ln, 喜歡cp或創建指向該目錄mv具有相同基名的另一個參數的連結。

或與zsh

ln -sf -- $FROM_DIR:P/* $TO_DIR/

如果$FROM_DIR無法確定 的真實路徑或在$FROM_DIR.

(添加D限定符還可以為隱藏文件創建符號連結)。

ln或者,如果您出於某種原因確實需要為每個文件呼叫一次:

for f ($FROM_DIR:P/*(ND)) ln -sfT -- $f $TO_DIR/$f:t

(注意-n-T是非標準擴展)。

要使用 shell 命令替換 with xargs(或在這裡, with find -exec, usingxargs將毫無意義),您需要它們來執行 shell:

TO_DIR=$TO_DIR find "$(realpath -- "$FROM_DIR")" -mindepth 1 -maxdepth 1 \
 -exec sh -c '
   for file do
     ln -sfn -- "$file" "$TO_DIR/$(basename -- "$file")"
   done' sh {} +

但請記住,basename不能用於任意文件的命令替換,因為命令替換會刪除所有尾隨換行符(這裡有同樣的問題$(realpath))。你最好使用sh’s${file##*/}zsh $file:there ( $FROM_DIR:Pfor realpath)。

在這裡,您只需要:

find "$(realpath -- "$FROM_DIR")" -mindepth 1 -maxdepth 1 \
 -exec ln -sft "$TO_DIR" -- {} +

雖然(-t也是一個 GNU 擴展)。如果文件太多(在 中,您可以通過使用或載入模組以獲取 的內置版本來解決此問題),則該錯誤不受太多參數錯誤的影響。$TO_DIR``zsh``zargs``zsh/files``ln

有關您嘗試的其他問題,另請參閱這些問答:

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