Bash
管道查找到 xargs 在終端中有效,但在 shell 腳本中無效
我正在嘗試編寫一個 Bash shell 腳本,它將目前目錄中的所有文件(減去一些例外)複製到另一個目錄中。該腳本建構一個命令,將其儲存在一個變數中,然後執行它。這是令人困惑的部分:當它建構的命令在 shell 腳本中執行時,它會失敗並顯示消息
find: paths must precede expression:
|xargs’如果我刪除 . 之前的空格
|,我會看到
find: unknown predicate-i'
. 但是當我echo
使用它建構並執行它的命令時,它工作正常!更奇怪的是,echo "$cmd"|bash
失敗並顯示相同的錯誤消息!腳本(
synchronize.sh
):#! /bin/bash EXCLUDED_FILES=(folder1 file.txt synchronize.sh) FLAGS='-r' PROJECT_NAME=project TARGET_DIR=$HOME/Documents/IDE/$PROJECT_NAME/assets cmd='find ./* -maxdepth 0' cmd_end="|xargs -i cp -r {} -t $TARGET_DIR" for file in ${EXCLUDED_FILES[@]} do cmd+=" ! -name \"$file\"" done cmd+=$cmd_end $cmd #Running the command directly fails #echo $cmd #Yet copying and pasting the output of this command will work just fine #echo "$cmd"|bash #Though this inexplicably fails, with the same message as just $cmd
所有文件或文件夾的名稱中都沒有空格,也沒有任何特殊字元(下劃線和句點除外)。
因此,在@KamilMaciorowski 連結的答案中,我了解到 Bash 在執行命令的字元串中對管道的處理方式不同。
$cmd
我通過將線路更改為解決了這個問題,eval "$cmd"
現在效果很好!請注意,
eval
可能會導致程式碼注入問題,但這與此特定腳本無關。
您對將列表載入到命令有一個好主意,但是有更好的方法來組合變數和命令。
@KamilMaciorowski 在這裡提供了一些很好的背景資訊,但您可能仍在四處尋找更明確的答案。通過在此處閱讀更多內容,您可以看到一個很好的範例,用於
printf
將數組格式化為find
命令。在您的情況下,這將是這樣的:
find ./* -maxdepth 0 $(printf "! -name %s " $EXCLUDED_FILES) -exec cp -r {} $TARGET_DIR \;