Прежде всего, не используйте 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"' {} \;