簡體   English   中英

在bash腳本中將參數回傳到xargs

[英]Echoing arguments into xargs in a bash script

我想將一些目錄傳遞給bash腳本,然后將這些目錄傳遞給xargs來並行工作。 不幸的是,我無法讓腳本執行我想要的事情。

這是一個與我的腳本等效的腳本,在此腳本中使用帶引號和不帶引號的情況:

echo $@ | xargs -i --max-procs=12 echo "do work in {}"
echo "$@" | xargs -i --max-procs=12 echo "do work in {}"

輸出:

$ ./script.sh d*
do work in d1 d2 d3 d4 d5 d6 d7 d8 d9
do work in d1 d2 d3 d4 d5 d6 d7 d8 d9
$ ./script.sh "d*"
do work in d1 d2 d3 d4 d5 d6 d7 d8 d9
do work in d*

您可能已經猜到了,我想要的是:

$ ./script.sh d*
do work in d1
do work in d2
do work in d3
do work in d4
do work in d5
do work in d6
do work in d7
do work in d8
do work in d9

在這種特定情況下, find在腳本中使用find ,但是將來我可能不想使用目錄。 例如,如果我要傳遞要創建的文件列表,則find將沒有用。

如何使xargs接受每個參數作為單獨的項目?

下面是經過測試的版本,只是為了進一步說明Jack Yates的原始問題:

printf "%s\0" "$@" | xargs -0 -I xxx --max-procs=4 printf "do work in %s\n" 'xxx'

printf不是處理位置參數的標准方法(對嗎?) .

我知道,與while循環和移位所需的處理數量相比,它非常有效。 根據對POSIX標准的實際應用信息部分echo ,所述printf內置命令為優選的替換echo

在以下條件下對此進行了測試:

  • 超過10000個目錄
  • man ascii中發現的所有特殊和不可打印的字符都已在目錄名稱中使用
  • printf,xargs和bash的手冊頁以及測試證實了Charles Duffy的評論。

事先答復(供參考)

以下版本以供參考。 如查爾斯·達菲(Charles Duffy)所寫,當目錄名稱中包含特殊字符時,它將生成錯誤。

-L 1選項指示xargs分別處理每行。

while [ $# -gt 0 ] ; do echo "${1}"; shift; done \
  | xargs -L 1 -I xxxx --max-procs=12 echo do work in "xxxx"

考試:

$ testscript.sh  .??* *
do work in .bashrc
do work in Downloads
do work in h2-1.2.139.jar
do work in install
do work in testscript.sh

通常, shift用於從命令行解析參數。

-I xxxx已被使用,因為根據xargs手冊頁不推薦使用-i

如果要將任意參數傳遞給xargs ,則唯一安全的方法-正確處理所有可能的文件名,包括帶文字引號,空格或其他格式的文件名-對其進行NUL分隔並使用xargs -0 從而:

printf '%s\0' "$@" | xargs -0 sh -c 'for f; do printf "do work in %s\n" "$@"; done'

否則,像$'hello\\nworld'這樣的參數( $'hello\\nworld'包含一個換行符)將被視為xargs中的兩個參數,而不是真正的單個參數。

我對此有困難的原因是-i-I選項更改了xargs期望的分隔符。 即, echo "$@" | xargs -n 1 do-something echo "$@" | xargs -n 1 do-something 確實可以按預期工作(注意: 如果文件名不正常,此方法會有一些警告 ;有關更多信息,請參見其他答案),但是echo "$@" | xargs -I{} -n 1 do-something {} echo "$@" | xargs -I{} -n 1 do-something {}不行。 使用-I-i標志,分隔符成為換行符。

例如:

$ cat test.sh 
echo "$@" | xargs -n 1 echo "do work in" 
echo "$@" | xargs -n 1 -I{} echo "do work in {}"
$ ls
./  ../  d1/  d2/  d3/  d4/  d5/  d6/  d7/  d8/  d9/  test.sh*
$ ./test.sh d*
do work in d1
do work in d2
do work in d3
do work in d4
do work in d5
do work in d6
do work in d7
do work in d8
do work in d9
do work in d1 d2 d3 d4 d5 d6 d7 d8 d9

來自man xargs

   -I replace-str
          Replace occurrences of replace-str in the initial-arguments with names read
          from standard input.  Also, unquoted blanks do not terminate  input  items;
          instead the separator is the newline character.  Implies -x and -L 1.

注意:根據123對原始問題的評論, -i已棄用:

   -i[replace-str]
          This option is a synonym for -Ireplace-str if replace-str is specified, and
          for -I{} otherwise.  This option is deprecated; use -I instead.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM