Haluan kirjoittaa komentosarjan, joka käyttää argumenttina .txt
-tiedostonimeä, lukee tiedostorivin rivillä ja välittää kukin rivi komennolle. Esimerkiksi se suorittaa command --option "LINE 1"
, sitten command --option "LINE 2"
jne. Komennon lähtö on kirjoitettu toiseen tiedostoon. Kuinka teen sen? En tiedä mistä aloittaa.
Vastaa
Käytä while read
-silmukkaa:
: > another_file ## Truncate file. while IFS= read -r LINE; do command --option "$LINE" >> another_file done < file
Toinen on ohjata ulostulo lohkolla:
while IFS= read -r LINE; do command --option "$LINE" done < file > another_file
Viimeinen on tiedoston avaaminen:
exec 4> another_file while IFS= read -r LINE; do command --option "$LINE" >&4 echo xyz ## Another optional command that sends output to stdout. done < file
Jos joku komennoista lukee syötettä, se olisi hyvä idea käyttää toista fd: tä syötteenä, jotta komennot eivät syö sitä (tässä olettaen ksh
, zsh
tai bash
kohteelle -u 3
, käytä sen sijaan kannettavasti <&3
:
while IFS= read -ru 3 LINE; do ... done 3< file
Fin liittolainen hyväksymään argumentit, voit tehdä seuraavaa:
#!/bin/bash FILE=$1 ANOTHER_FILE=$2 exec 4> "$ANOTHER_FILE" while IFS= read -ru 3 LINE; do command --option "$LINE" >&4 done 3< "$FILE"
Kumpi voisi toimia nimellä:
bash script.sh file another_file
Ylimääräinen idea. Käytä bash
-kohdassa readarray
:
readarray -t LINES < "$FILE" for LINE in "${LINES[@]}"; do ... done
Huomaa: IFS=
voidaan jättää pois, jos et halua, että viiva-arvot on leikattu etu- ja lopputiloista.
Vastaa
Toinen vaihtoehto on xargs
.
GNU: lla xargs
:
xargs -a file -I{} -d"\n" command --option {} other args
{}
on tekstirivin paikanpitäjä.
Muu xargs
ei yleensä ole -a
, -d
, mutta joillakin on -0
NUL-erotetulle tulolle. Niillä voit tehdä seuraavaa:
< file tr "\n" "\0" | xargs -0 -I{} command --option {} other args
Unix-yhteensopivissa järjestelmissä (-I
on valinnainen POSIX-järjestelmässä ja vain vaaditaan UNIX-yhteensopiville järjestelmille), sinun on esikäsiteltävä syöte lainaamaan rivit xargs
:
< file sed "s/"/"\\""/g;s/.*/"&"/" | xargs -E "" -I{} command --option {} other args
Huomaa kuitenkin, että joillakin xargs
-toteutuksilla on hyvin pieni argumentin enimmäiskoko (esimerkiksi Solariksessa 255, Unix-määrityksen sallima vähimmäismäärä).
Kommentit
Vastaa
Pitää tarkasti kysymykseen:
#!/bin/bash # xargs -n param sets how many lines from the input to send to the command # Call command once per line [[ -f $1 ]] && cat $1 | xargs -n1 command --option # Call command with 2 lines as args, such as an openvpn password file # [[ -f $1 ]] && cat $1 | xargs -n2 command --option # Call command with all lines as args # [[ -f $1 ]] && cat $1 | xargs command --option
kommentit
- toimi kuin viehätys 🙂
- +1 rakasti tätä, kiitos
Vastaa
Paras vastaus und is:
for i in `cat`; do "$cmd" "$i"; done < $file
MUOKKAA:
… neljä vuotta myöhemmin …
useiden alas-äänestysten ja jonkin verran kokemuksen jälkeen suosittelisin seuraavaa nyt:
xargs -l COMMAND < file
Kommentit
- Tämä kutsuu komennon kerran jokaiselle tiedoston sanalle . Sinun tulee myös lainata viittauksia kuorimuuttujiin (kuten kohdassa
do "$cmd" "$i";
), ellei sinulla ole syytä olla; jos tiedosto sisältäisi itsessään sanana*
, koodisi toimisi$cmd *
, joka tietysti ajaisi komennon luettelo nykyisen hakemiston tiedostoista. - @ G-Man, lukuun ottamatta
zsh
,`cat`
laajentaisi jo*
(noteeraamaton$i
voisi edelleen laajentaa jokerimerkkiä (toinen kierros), jos`cat`
esittelee joitain). Joka tapauksessa tämä lähestymistapa on todellakin väärä. - +1. Tämä toimii hyvin, jos jokainen rivi sisältää vain syötteen, joka tarvitaan komennolle ilman välilyöntejä.
- +1, tykkäsi xargs-ratkaisusta
- Tämä toimii! (myöhempi muokkaus
xargs -l COMMAND < file
). Kiitos!
Vastaa
sed "s/"/"\\\\""/g;s/.*/\$* "&"/" <<\FILE |\ sh -s -- command echo --option all of the{&}se li$n\es "are safely shell quoted and handed to command as its last argument following --option, and, here, before that echo FILE
LÄHTÖ
--option all of the{&}se li$n\es "are safely shell --option quoted and handed to command as its last argument --option following --option, and, here, before that echo
Vastaa
ed file.txt %g/^/s// / 2,$g/^/-,.j 1s/^/command/ wq chmod 755 file.txt ./file.txt
Ota kaikki tiedoston rivit ja välittää ne argumentteina yhteen komentoon, ts.
command line1 line2 line3 ....
Jos tarvitset --option
jokaista riviä edeltävä lippu vaihtaa toisen komennon muotoon:
%g/^/s// --option /
Kommentit
- Mikä -1 käyttää ed … todella?
- En ' äänestänyt sinua alhaalla, mutta henkilöllä, jolla oli todennäköisesti seuraavat syyt: (1) Tämä ei tee mitä kysymys kysyy. Tämä kutsuu komennon kerran ja koko tiedoston sisältö komentorivillä. pikemminkin kuin kerran riviä kohti .(2) Tämä ei tee mitään sellaisten merkkien käsittelemiseksi, jotka ovat erityisiä kuorelle (jotka voivat olla tiedostossa) esim.
'
,"
,<
,>
,;
jne. (3) Tämä luo tarpeettoman väliaikaisen tiedoston. (4) Tällaiset asiat tehdään yleensä ”täällä asiakirjoilla”. (5)ed
-komennosi ovat kömpelöitä; kaksi ensimmäistä komentoa voidaan pienentää muotoon%s/^/ /
ja%j
.
<file xargs -L 1 -I{} command --option {} other args