Перш за все, не використовуйте 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"' {} \;