Diyelim ki argümanları foo.txt
belirten bir N
dosyam var
arg1
arg2
...
argN
ki komuta geçmem gerekiyor my_command
Bir dosyanın satırlarını komutun bağımsız değişkenleri olarak nasıl kullanabilirim?
Diyelim ki argümanları foo.txt
belirten bir N
dosyam var
arg1
arg2
...
argN
ki komuta geçmem gerekiyor my_command
Bir dosyanın satırlarını komutun bağımsız değişkenleri olarak nasıl kullanabilirim?
Yanıtlar:
Kabuğunuz bash ise (diğerlerinin yanı sıra), kısayolu $(cat afile)
şudur $(< afile)
:
mycommand "$(< file.txt)"
'Komut Değiştirme' bölümündeki bash man sayfasında belgelenmiştir.
Alternatif olarak, komutunuzu stdin'den okuyun, bu yüzden: mycommand < file.txt
<
operatörü kullanmak için bir kısayol değildir . Bu, kabuğun, cat
yönlendirme özellikleri için ikili dosyayı yürütmek yerine yeniden yönlendirmeyi gerçekleştireceği anlamına gelir .
"$(…)"
, içeriği argüman olarak değil file.txt
, standart girdisine aktarılır mycommand
. komutu çalıştırmak ve çıktıyı dize olarak geri vermek"$(…)"
anlamına gelir ; burada “komut” sadece dosyayı okur, ancak daha karmaşık olabilir.
Daha önce de belirtildiği gibi, ters tırnakları veya kullanabilirsiniz $(cat filename)
.
Bahsetmediğim ve not edilmesi gereken önemli olan, kabuğun, boşluğa göre o dosyanın içeriğini parçalayacağını ve komutunuza bir argüman olarak bulduğu her "sözcüğü" vereceğini hatırlamanız gerektiğidir. Boşluk, kaçış dizileri vb. İçerebilmesi için bir komut satırı bağımsız değişkenini tırnak içine alabilmenize rağmen, dosyadan okumak aynı şeyi yapmaz. Örneğin, dosyanız şunları içeriyorsa:
a "b c" d
alacağınız argümanlar:
a
"b
c"
d
Her satırı bağımsız değişken olarak çekmek istiyorsanız while / read / do yapısını kullanın:
while read i ; do command_name $i ; done < filename
read -r
Ters eğik çizgi-kaçış dizilerini genişletmek istemediğiniz sürece okuma olmalıdır - ve NUL, özellikle geçmekte olduğunuz argümanlar gerçek adlar içeren dosya adları gibi şeyler ise, yeni satırdan daha güvenli bir sınırlayıcıdır. Ayrıca, IFS'yi temizlemeden, dolaylı olarak temizlenen önde gelen ve sondaki boşlukları elde edersiniz i
.
command `< file`
dosya içeriğini stdin'deki komuta iletir, ancak yeni satırları çıkarır, yani her satır üzerinde ayrı ayrı yineleme yapamazsınız. Bunun için 'for' döngüsüne sahip bir komut dosyası yazabilirsiniz:
for line in `cat input_file`; do some_command "$line"; done
Veya (çok satırlı varyant):
for line in `cat input_file`
do
some_command "$line"
done
Veya ( $()
yerine çok satırlı varyant ``
):
for line in $(cat input_file)
do
some_command "$line"
done
< file
tıklamaları, aslında hiç bir yönlendirme gerçekleştirmediği anlamına gelir command
.
command `< file`
çalışmaz ; zsh farklı bir konudur, ancak bu sorunun konusu olan kabuk bu değildir).
Hello World
Bir satıra koy . Bunu ilk çalıştırmak göreceksiniz some_command Hello
, sonra some_command World
, değil some_command "Hello World"
veya some_command Hello World
.
Bunu ters çentikler kullanarak yaparsınız:
echo World > file.txt
echo Hello `cat file.txt`
echo "Hello * Starry * World" > file.txt
ilk adımda yayınlarsanız , ikinci komuta en az dört ayrı argüman iletilirsiniz - ve muhtemelen gibi daha *
s dosyaların adlarına artıracağı geçerli dizinde sunuyoruz.
fork()
stdoutuna bağlı bir FIFO ile bir /bin/cat
alt kabuktan çıkıyor, daha sonra bu alt kabuğun bir çocuğu olarak çağırıyor ve daha sonra çıktıyı FIFO üzerinden okuyor; $(<file.txt)
dosyanın içeriğini alt kabuklar veya FIFO'lar olmadan doğrudan bash'a okuyan ile karşılaştırın .
Bunu mümkün olan her komut satırı argümanı (boşluklu değerler, satırsonu değerleri, değişmez tırnak karakterleri içeren değerler, yazdırılamayan değerler, glob karakterleri olan değerler, vb.) İçin çalışan sağlam bir şekilde yapmak istiyorsanız, biraz daha ilginç.
Bir dosyaya yazmak için, bir dizi argüman verildi:
printf '%s\0' "${arguments[@]}" >file
... ile değiştirin "argument one"
, "argument two"
uygun olarak, vb.
Bu dosyadan okumak ve içeriğini kullanmak için (bash, ksh93 veya dizileri olan yeni bir kabukta):
declare -a args=()
while IFS='' read -r -d '' item; do
args+=( "$item" )
done <file
run_your_command "${args[@]}"
Bu dosyadan okumak ve içeriğini kullanmak için (dizileri olmayan bir kabukta; bunun yerel komut satırı bağımsız değişken listenizin üzerine yazacağını ve bu nedenle en iyi şekilde işlevin bağımsız değişkenlerinin üzerine yazacağınızı, genel liste):
set --
while IFS='' read -r -d '' item; do
set -- "$@" "$item"
done <file
run_your_command "$@"
Not -d
(farklı sonu hattı ayraç kullanılmasına izin veren) bir POSIX olmayan uzantısıdır ve diziler olmayan bir kabuk da bunu desteklemez. Bu durumda, NUL ile sınırlandırılmış içeriği eval
güvenli bir forma dönüştürmek için kabuk olmayan bir dil kullanmanız gerekebilir :
quoted_list() {
## Works with either Python 2.x or 3.x
python -c '
import sys, pipes, shlex
quote = pipes.quote if hasattr(pipes, "quote") else shlex.quote
print(" ".join([quote(s) for s in sys.stdin.read().split("\0")][:-1]))
'
}
eval "set -- $(quoted_list <file)"
run_your_command "$@"
Bir dosyanın içeriğini bir komuta bağımsız değişken olarak nasıl aktarırım:
./foo --bar "$(cat ./bar.txt)"
$(<bar.txt)
(bash gibi bir kabuğu uygun uzantı ile kullanırken). $(<foo)
özel bir durumdur: normal komut ikamesinin aksine, kullanıldığı gibi $(cat ...)
, bir alt kabuğun çalışması için çatallanamaz ve bu nedenle büyük bir yükü önler.
Tek yapmanız gereken dosyayı arguments.txt
içerikle çevirmek
arg1
arg2
argN
içine my_command arg1 arg2 argN
sadece kullanabilirsiniz xargs
:
xargs -a arguments.txt my_command
Sen ek statik argümanlar koyabilirsiniz xargs
gibi çağrı xargs -a arguments.txt my_command staticArg
hangi arayacakmy_command staticArg arg1 arg2 argN
Benim bash kabuğumda bir cazibe gibi çalıştı:
cat input_file | xargs -I % sh -c 'command1 %; command2 %; command3 %;'
girdi_dosyası
arg1
arg2
arg3
Açıkça görüldüğü gibi, input_file dosyasındaki her satırda birden fazla komut çalıştırmanıza izin verir, burada öğrendiğim güzel bir numara .
$(somecommand)
, o komutu metin olarak iletmek yerine çalıştırırsınız. Benzer şekilde, >/etc/passwd
yeniden yönlendirme ve üzerine yazma /etc/passwd
(uygun izinlerle çalıştırılırsa) vb. Olarak işlenecektir
xargs -d $'\n' sh -c 'for arg; do command1 "$arg"; command2 "arg"; command3 "arg"; done' _
- ve aynı zamanda daha etkilidir, çünkü giriş dosyanızdaki her satır için bir kabuk başlatmak yerine mümkün olduğunca çok sayıda argüman iletir.
cat
@Wesley Rice'ın cevabını birkaç kez düzenledikten sonra , değişikliklerimin kendi cevabımı yazmak yerine cevabını değiştirmeye devam etmek için çok büyük olduğuna karar verdim. Ben de kendiminkini yazmam gerektiğine karar verdim!
Bir dosyanın her satırını okuyun ve üzerinde satır satır çalışın:
#!/bin/bash
input="/path/to/txt/file"
while IFS= read -r line
do
echo "$line"
done < "$input"
Bu doğrudan yazar Vivek Gite'den geliyor: https://www.cyberciti.biz/faq/unix-howto-read-line-by-line-from-file/ . Krediyi alır!
Sözdizimi: Bash Unix ve Linux kabuğunda dosyayı satır satır okuyun:
1. Sözdizimi, bir dosyayı satır
2 okumak için bash, ksh, zsh ve diğer tüm kabuklar için aşağıdaki gibidir .while read -r line; do COMMAND; done < input.file
3.-r
Seçenek, okuma komutuna geçti ters eğik çizgi kaçışlarının yorumlanmasını engeller.
4.IFS=
Öndeki / arkadaki boşlukların kırpılmasını önlemek için okuma komutundan önce seçenek ekleyin -
5.while IFS= read -r line; do COMMAND_on $line; done < input.file
Ve şimdi de şu anda kapalı olan bu soruyu cevaplamak için: Bir dosyadaki dosyaların listesini `` git '' mümkün müdür? - işte cevabım:
FILES_STAGED
Her satırın yapmak istediğim bir dosyaya göreli bir yol olduğu bir grup satır içeren bir dosyanın mutlak yolunu içeren bir değişken olduğunu unutmayın git add
. Bu kod parçacığı parçası olmak üzeredir "eRCaGuy_dotfiles / useful_scripts / sync_git_repo_to_build_machine.sh" başka (ex: Bir PC (bir bilgisayar ben kod ex): dan gelişiminde dosyaların kolay senkronizasyonu sağlamak için, bu projede dosyanın bir daha güçlü bir bilgisayar geliştiriyorum): https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles .
while IFS= read -r line
do
echo " git add \"$line\""
git add "$line"
done < "$FILES_STAGED"
git add
üzerinde nasıl çalışabilirim: Bir dosyadaki dosyaların listesini `` git '' mümkün müdür?