Прежде всего, не используйте ls
вывод как список файлов . Используйте расширение оболочки или find
. Ниже приведены возможные последствия неправильного использования ls + xargs и пример правильного xargs
использования.
1. Простой способ: для цикла
Если вы хотите обрабатывать только файлы, расположенные ниже A/
, то простого for
цикла должно быть достаточно:
for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; done
2. pre1 Почему бы и нет ls | xargs
?
Вот пример того, как плохие вещи могут обернуться, если вы используете ls
с 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.dat
и другое mypreciousfile.dat.ans
. Если бы в этих файлах было какое-либо содержимое, оно было бы стерто.
2. Использование xargs
: правильно с find
Если вы хотите настаивать на использовании xargs
, используйте -0
(имена, оканчивающиеся нулем):
find A/ -name "*.dat" -type f -print0 | xargs -0 -I file sh -c './a.out < "file" > "file.ans"'
Обратите внимание на две вещи:
- таким образом, вы будете создавать файлы с
.dat.ans
окончанием;
- это сломается, если какое-либо имя файла содержит знак кавычки (
"
).
Обе проблемы могут быть решены с помощью различных способов вызова оболочки:
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"' {} \;