Pertama-tama, jangan gunakan ls
output sebagai daftar file . Gunakan ekspansi shell atau find
. Lihat di bawah ini untuk konsekuensi potensial dari penyalahgunaan ls + xargs dan contoh xargs
penggunaan yang tepat .
1. Cara sederhana: untuk loop
Jika Anda ingin memproses hanya file-file di bawah A/
, maka for
loop sederhana harus cukup:
for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; done
2. pre1 Kenapa tidak ls | xargs
?
Berikut ini adalah contoh bagaimana hal-hal buruk bisa berubah jika Anda menggunakan ls
dengan xargs
untuk pekerjaan itu. Pertimbangkan skenario berikut:
pertama, mari kita buat beberapa file kosong:
$ touch A/mypreciousfile.dat\ with\ junk\ at\ the\ end.dat
$ touch A/mypreciousfile.dat
$ touch A/mypreciousfile.dat.ans
lihat file dan tidak mengandung apa pun:
$ ls -1 A/
mypreciousfile.dat
mypreciousfile.dat with junk at the end.dat
mypreciousfile.dat.ans
$ cat A/*
jalankan perintah ajaib menggunakan xargs
:
$ ls A/*.dat | xargs -I file sh -c "echo TRICKED > file.ans"
hasil:
$ cat A/mypreciousfile.dat
TRICKED with junk at the end.dat.ans
$ cat A/mypreciousfile.dat.ans
TRICKED
Jadi, Anda baru saja berhasil menimpa keduanya mypreciousfile.dat
dan mypreciousfile.dat.ans
. Jika ada konten dalam file itu, itu akan dihapus.
2. Menggunakan xargs
: cara yang tepat dengan find
Jika Anda ingin tetap menggunakan xargs
, gunakan -0
(nama yang dihentikan nol):
find A/ -name "*.dat" -type f -print0 | xargs -0 -I file sh -c './a.out < "file" > "file.ans"'
Perhatikan dua hal:
- dengan cara ini Anda akan membuat file dengan
.dat.ans
akhiran;
- ini akan rusak jika beberapa nama file berisi tanda kutip (
"
).
Kedua masalah dapat diselesaikan dengan cara doa shell yang berbeda:
find A/ -name "*.dat" -type f -print0 | xargs -0 -L 1 bash -c './a.out < "$0" > "${0%dat}ans"'
3. Semua dilakukan di dalam find ... -exec
find A/ -name "*.dat" -type f -exec sh -c './a.out < "{}" > "{}.ans"' \;
Ini, sekali lagi, menghasilkan .dat.ans
file dan akan pecah jika nama file berisi "
. Untuk melakukannya, gunakan bash
dan ubah cara pemanggilannya:
find A/ -name "*.dat" -type f -exec bash -c './a.out < "$0" > "${0%dat}ans"' {} \;