Katakanlah, saya punya file yang foo.txt
menentukan N
argumen
arg1
arg2
...
argN
yang perlu saya sampaikan ke perintah my_command
Bagaimana cara menggunakan baris file sebagai argumen dari suatu perintah?
Katakanlah, saya punya file yang foo.txt
menentukan N
argumen
arg1
arg2
...
argN
yang perlu saya sampaikan ke perintah my_command
Bagaimana cara menggunakan baris file sebagai argumen dari suatu perintah?
Jawaban:
Jika shell Anda adalah bash (antara lain), pintasannya
$(cat afile)
adalah$(< afile)
, jadi Anda akan menulis:Didokumentasikan di halaman bash man di bagian 'Pergantian Perintah'.
Alterately, minta perintah Anda dibaca dari stdin, jadi:
mycommand < file.txt
sumber
<
operator. Ini berarti bahwa shell itu sendiri akan melakukan redirection daripada mengeksekusicat
binary untuk properti redirection itu."$(…)"
, isifile.txt
akan diteruskan ke input standarmycommand
, bukan sebagai argumen."$(…)"
berarti menjalankan perintah dan mengembalikan output sebagai string ; di sini "perintah" hanya membaca file tetapi bisa jadi lebih kompleks.Seperti yang telah disebutkan, Anda dapat menggunakan backticks atau
$(cat filename)
.Apa yang tidak disebutkan, dan saya pikir penting untuk dicatat, adalah bahwa Anda harus ingat bahwa shell akan memecah konten file tersebut sesuai dengan spasi, memberikan setiap "kata" yang ditemukannya pada perintah Anda sebagai argumen. Dan sementara Anda mungkin bisa melampirkan argumen baris perintah dalam tanda kutip sehingga bisa berisi spasi, urutan melarikan diri, dll., Membaca dari file tidak akan melakukan hal yang sama. Misalnya, jika file Anda mengandung:
argumen yang akan Anda dapatkan adalah:
Jika Anda ingin menarik setiap baris sebagai argumen, gunakan konstruksi while / read / do:
sumber
read -r
kecuali Anda ingin memperluas urutan backslash-escape - dan NUL adalah pembatas yang lebih aman untuk digunakan daripada baris baru, terutama jika argumen yang Anda sampaikan adalah hal-hal seperti nama file, yang dapat berisi baris baru literal. Juga, tanpa membersihkan IFS, Anda bisa memimpin dan mengikuti spasi kosong secara implisit dibersihkani
.akan meneruskan konten file ke perintah pada stdin, tetapi akan menghapus baris baru, yang berarti Anda tidak dapat mengulangi setiap baris secara terpisah. Untuk itu Anda bisa menulis skrip dengan loop 'untuk':
Atau (varian multi-baris):
Atau (varian multi-baris dengan
$()
alih - alih``
):Referensi:
sumber
< file
backticks berarti tidak benar-benar melakukan pengalihancommand
sama sekali.command `< file`
Tidak berfungsi baik di bash atau POSIX sh; zsh adalah masalah yang berbeda, tapi itu bukan masalah yang ditanyakan oleh pertanyaan ini).Hello World
di satu baris. Anda akan melihatnya dijalankan pertama kalisome_command Hello
, kemudiansome_command World
, tidaksome_command "Hello World"
atausome_command Hello World
.Anda melakukannya dengan menggunakan backticks:
sumber
echo "Hello * Starry * World" > file.txt
pada langkah pertama, Anda akan mendapatkan setidaknya empat argumen terpisah dilewatkan ke perintah kedua - dan kemungkinan lebih lanjut, karena*
s akan diperluas ke nama-nama file yang ada di direktori saat ini.fork()
keluar dari subkulit dengan FIFO yang melekat pada stdout, kemudian memanggil/bin/cat
sebagai anak dari subkulit itu, kemudian membaca output melalui FIFO; dibandingkan dengan$(<file.txt)
, yang membaca konten file menjadi bash secara langsung tanpa subshell atau FIFO yang terlibat.Jika Anda ingin melakukan ini dengan cara yang kuat yang bekerja untuk setiap argumen baris perintah yang mungkin (nilai dengan spasi, nilai dengan baris baru, nilai dengan karakter kutipan literal, nilai yang tidak dapat dicetak, nilai dengan karakter glob, dll), itu akan sedikit lebih menarik.
Untuk menulis ke file, diberikan array argumen:
... ganti dengan
"argument one"
,"argument two"
, dll yang sesuai.Untuk membaca dari file itu dan menggunakan kontennya (dalam bash, ksh93, atau shell terbaru lainnya dengan array):
Untuk membaca dari file itu dan menggunakan isinya (dalam shell tanpa array; perlu diketahui bahwa ini akan menimpa daftar argumen baris perintah lokal Anda, dan dengan demikian paling baik dilakukan di dalam suatu fungsi, sehingga Anda menimpa argumen fungsi dan tidak daftar global):
Perhatikan bahwa
-d
(memungkinkan pembatas end-of-line yang berbeda untuk digunakan) adalah ekstensi non-POSIX, dan shell tanpa array juga mungkin tidak mendukungnya. Jika demikian, Anda mungkin perlu menggunakan bahasa non-shell untuk mengubah konten yang dibatasi NUL menjadieval
bentuk -safe:sumber
Inilah cara saya meneruskan konten file sebagai argumen ke perintah:
sumber
$(<bar.txt)
(saat menggunakan shell, seperti bash, dengan ekstensi yang sesuai).$(<foo)
adalah kasus khusus: tidak seperti substitusi perintah biasa, seperti yang digunakan$(cat ...)
, itu tidak memotong subkulit untuk beroperasi, dan dengan demikian menghindari banyak overhead.Jika semua yang perlu Anda lakukan adalah mengubah file
arguments.txt
dengan kontenke dalam
my_command arg1 arg2 argN
maka Anda cukup menggunakanxargs
:Anda dapat memasukkan argumen statis tambahan dalam
xargs
panggilan, sepertixargs -a arguments.txt my_command staticArg
yang akan dipanggilmy_command staticArg arg1 arg2 argN
sumber
Di bash shell saya yang berikut ini berfungsi seperti pesona:
di mana input_file berada
Sebagai bukti, ini memungkinkan Anda untuk mengeksekusi banyak perintah dengan setiap baris dari input_file, trik kecil yang bagus yang saya pelajari di sini .
sumber
$(somecommand)
, Anda akan mendapatkan perintah yang dieksekusi daripada diteruskan sebagai teks. Demikian juga,>/etc/passwd
akan diproses sebagai pengalihan dan ditimpa/etc/passwd
(jika dijalankan dengan izin yang sesuai), dll.xargs -d $'\n' sh -c 'for arg; do command1 "$arg"; command2 "arg"; command3 "arg"; done' _
- dan juga lebih efisien, karena ia meneruskan sebanyak mungkin argumen ke setiap shell daripada memulai satu shell per baris dalam file input Anda.cat
Setelah mengedit jawaban @Wesley Rice beberapa kali, saya memutuskan bahwa perubahan saya menjadi terlalu besar untuk terus mengubah jawabannya daripada menulis sendiri. Jadi, saya memutuskan untuk menulis sendiri!
Baca setiap baris file di dan operasikan baris demi baris seperti ini:
Ini datang langsung dari penulis Vivek Gite di sini: https://www.cyberciti.biz/faq/unix-howto-read-line-by-line-from-file/ . Dia mendapat pujian!
Dan sekarang untuk menjawab pertanyaan yang sekarang ditutup ini yang saya juga punya: Apakah mungkin untuk `git menambahkan` daftar file dari file?- inilah jawaban saya:
Perhatikan bahwa
FILES_STAGED
ini adalah variabel yang berisi path absolut ke file yang berisi banyak baris di mana setiap baris adalah path relatif ke file yang ingin saya lakukangit add
. Cuplikan kode ini akan menjadi bagian dari file "eRCaGuy_dotfiles / useful_scripts / sync_git_repo_to_build_machine.sh" dalam proyek ini, untuk memudahkan sinkronisasi file dalam pengembangan dari satu PC (mis: komputer tempat saya berkode ) ke yang lain (mis: komputer tempat saya berkode )) komputer yang lebih kuat yang saya bangun): https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles .Referensi:
Terkait:
git add
padanya: Apakah mungkin untuk `git menambah` daftar file dari file?sumber