Io-Redirection

帶有標準輸入/標準輸出重定向的 xargs

  • March 26, 2019

我想執行:

./a.out < x.dat > x.ans

對於目錄A中的每個 * .dat文件。

當然,它可以通過 bash/python/whatsoever 腳本來完成,但我喜歡寫性感的單線。我所能達到的只是(仍然沒有任何標準輸出):

ls A/*.dat | xargs -I file -a file ./a.out

但是xargs 中的*-a*不理解 replace-str ‘file’。

謝謝你的幫助。

首先,不要將ls輸出用作文件列表。使用外殼擴展或find. 有關ls+xargs誤用的潛在後果和正確xargs使用的範例,請參見下文。

1.簡單方式:for循環

如果您只想處理 下的文件A/,那麼一個簡單的for循環就足夠了:

for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; done

2. pre1為什麼不   ls | xargs 呢?

這是一個例子,說明如果你在工作中使用lswith ,事情可能會變得多麼糟糕。xargs考慮以下場景:

  • 首先,讓我們創建一些空文件:
$ touch A/mypreciousfile.dat\ with\ junk\ at\ the\ end.dat
$ touch A/mypreciousfile.dat
$ touch A/mypreciousfile.dat.ans
  • 查看文件並且它們不包含任何內容:
$ ls -1 A/
mypreciousfile.dat
mypreciousfile.dat with junk at the end.dat
mypreciousfile.dat.ans

$ cat A/*
  • 使用以下命令執行魔術命令xargs
$ ls A/*.dat | xargs -I file sh -c "echo TRICKED > file.ans"
  • 結果:
$ cat A/mypreciousfile.dat
TRICKED with junk at the end.dat.ans

$ cat A/mypreciousfile.dat.ans
TRICKED

所以你剛剛設法覆蓋了mypreciousfile.datmypreciousfile.dat.ans。如果這些文件中有任何內容,它就會被刪除。


2.使用  xargs :正確的方法  find

如果您想堅持使用xargs,請使用-0(null-terminated names) :

find A/ -name "*.dat" -type f -print0 | xargs -0 -I file sh -c './a.out < "file" > "file.ans"'

注意兩點:

  1. 這樣,您將創建帶有.dat.ans結尾的文件;
  2. 如果某些文件名包含引號 ( ),這將中斷。"

這兩個問題都可以通過不同的 shell 呼叫方式來解決:

find A/ -name "*.dat" -type f -print0 | xargs -0 -L 1 bash -c './a.out < "$0" > "${0%dat}ans"'

3. 全部在內部完成find ... -exec

find A/ -name "*.dat" -type f -exec sh -c './a.out < "{}" > "{}.ans"' \;

這再次生成.dat.ans文件,如果文件名包含". 為此,請使用bash並更改它的呼叫方式:

find A/ -name "*.dat" -type f -exec bash -c './a.out < "$0" > "${0%dat}ans"' {} \;

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