Mi lesz, öreg koromra, ha már most is teljesen elhülyülök?
A legegyszerűbb dolgokra sem emlékszem.
Van egy fájlom, benne sorok, és a sorokban szóközzel elválasztva szavak (path/fájlnév).
Szeretnék egy ciklust, ami végigmegy a sorokon.
aztán eltároljuk az első nevet,
majd egy belső ciklusban végig az összes többin.
Holt egyszerű. Csak nem emlékszem, hogy is kellene nekilátni.
Odáig eljutottam, hogy while read line; valami $line; done < file
Valószínű egy for ciklussal végig tudok menni az összes szón, de nem tudom, hogy vegyem ki az elsőt.
Ha majd össze is áll, félek, mi lesz az eredmény :-)
Szóval útmutatást szeretnék. Esetleg azt, hogy kellett volna jobban megcsinálni.
- 4656 megtekintés
Hozzászólások
#!/bin/bash
IFS=' '
while read first second; do
echo ">>>$first"
echo "+++$second"
done < "$1"
---%<---
$ x.sh x.sh
>>>#!/bin/bash
+++
>>>
+++
>>>IFS='
+++'
>>>
+++
>>>while
+++read first second; do
>>>echo
+++">>>$first"
>>>echo
+++"+++$second"
>>>done
+++< "$1"
- A hozzászóláshoz be kell jelentkezni
OK, szóval így tudom kivenni az elsőt, külön a maradéktól.
Klassz. Ezzel tovább tudok lépni.
Köszi
- A hozzászóláshoz be kell jelentkezni
Áh... a read úgy működik, hogy megadhatsz neki egy vagy több változónevet, és azokba teszi az IFS által meghatározott szavakat, illetve az utolsóba a maradékot.
Ezt én úgy szoktam használni, hogy ha adott egy csv pl:
:Kiss:János:asztalos:
Akkor ezt négy változóba olvasom be (vezeték- és keresztnév, beosztás, garbage) és ha van, akkor az utolsóba teszi a szemetet.
- A hozzászóláshoz be kell jelentkezni
Na ez lett az eredmény:
while read one two; do
for i in $two; do
echo valami $one $i
done
done < file
Ez nekem most elég is.
De ha meg lehetett volna jobban is oldani, nyugodtan mondjátok!
- A hozzászóláshoz be kell jelentkezni
Egy gondom van a string alapú feldolgozással: mi történik, ha valamelyik fájlnak vagy könyvtárnak a nevében szóköz van? Az említett szoftvert nem ismerem, nem tudom, mit csinál a fájlnévben lévő spec.karakterekkel.
- A hozzászóláshoz be kell jelentkezni
shellben nincs olyan hogy jobban :) minden shell scriptnel lehet talalni valamit amire elhasal. A lenyeg, hogy percek allat osszedobsz valamit, ami a konkret feladatot akkor egyszer megoldja. csak ne publikald mint szoftvert..
- A hozzászóláshoz be kell jelentkezni
Igen, a tesztelés során ebbe belefutottam.
Az fdupes escape-et használ a szóközökhöz, pl.:
fdupes\ teszt/b/P2140557.JPG fdupes\ teszt/a/P2140557.JPG
Ez lett a megoldás:
for i in "$two"; do
- A hozzászóláshoz be kell jelentkezni
Hát lehet, hogy én vagyok ügyetlen, de nekem ebben a verzióban nem működött, csak ha tömbbe olvastam be a sorokat.
Úgy viszont tényleg jó volt.
- A hozzászóláshoz be kell jelentkezni
Így valóban nem volt tökéletes. Ha egy sorban legalább három szóközöket is tartalmazó elérési út szerepelt, akkor az első még jó volt, de a read az escape-eket kiszedte, és így a maradékot nem lehetett rendesen szétvágni.
Végül, ahogy javasoltad, tömböt használtam.
Ez lett a végeredmény:
while read -a two; do
one="${two[0]}"
unset two[0];
for i in "${two[@]}"; do
rm "$i"
ln "$one" "$i"
done
done < $1
Az eredménnyel elégedett vagyok, hiszen működik, de a shell tömb kezelését megtanulni hozzá az kicsit több volt, mint amire számítottam.
Azt hittem egyszerűbben (új dolog megtanulása nélkül) is meg lehet oldani.
Lehet, hogy pythonban kellett volna megírnom, csak éppen feltételeztem, hogy shell scriptben hipp-hopp megvan, ha sikerül visszaemlékeznem a dolgokra.
- A hozzászóláshoz be kell jelentkezni
"Azt hittem egyszerűbben (új dolog megtanulása nélkül) is meg lehet oldani."
Nem mondom, hogy szépen (és itt meg a fájlnevekben előforduló aposztrófok okoznának gondot), de lehet.
while read -r all; do
[ -z "$all" ] && continue
all=`echo "$all" | sed -e 's/\\\\ /@@szokoz@@/g'`
set -- $all
FIRST=`echo $1 | sed -e 's/@@szokoz@@/ /g'`; shift
while [ $# -gt 0 ]; do
NEXT=`echo $1 | sed -e 's/@@szokoz@@/ /g'`; shift
echo "ln -f '$FIRST' '$NEXT'"
done
done < txt
- A hozzászóláshoz be kell jelentkezni
Meg a filenevekben található @@szokoz@@ is gondot okozna szerintem.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Garantáltan. És persze nincs olyan perverz tempsztring, ami ne okozna, ha a fájlnevek alkotója még perverzebb, mint a szkripté.
- A hozzászóláshoz be kell jelentkezni
Lehetne úgy is, hogy minden &-et &-ra, majd minden backslash space-t -re.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Persze.
Mondjuk, akkor az volna a kérdés, hogy melyik letöltő/böngésző van annyira elcseszve/kiokosítva, hogy juszt is URL-kódolva írta az általa leszedett fájlok nevét.
Ahogy egy kolléga utalt rá, shellben humán felülvizsgáló nélkül eléggé végtelenbe nyúlik az ilyen történet.
Éppen ezért amikor (ötévente egyszer) kócos fájlneveket fésülök, mindig legenerálom a vonatkozó szkriptet, abból kigrepelem azt a néhányat, ami annyira egzotikus, hogy kézzel biztosabb elbánni vele, a maradék meg marad a szkriptben és chmod 700, ./fussahogytudsz.
- A hozzászóláshoz be kell jelentkezni
Izé... mi lenne a kívánt végeredmény? Mert szerintem félreértem:
in.txt:
path file name
path2 file2 name
path3 file name3
script.sh:
#!/bin/bash
while read Line
do
for Word in ${Line}
do
echo -n \""${Word}"\"\
done
echo ""
done < in.txt
A vég és eredmény:
fisher@ap:/tmp$ ./script.sh
"path" "file" "name"
"path2" "file2" "name"
"path3" "file" "name3"
- A hozzászóláshoz be kell jelentkezni
Egy fdupes kimeneten akarok végigmenni, letörölni a második és többedik fájlokat, aztán hardlinkelni az elsőről azokat, amiket letöröltem.
- A hozzászóláshoz be kell jelentkezni
Ez ugyan nem pontosan az, amit akarsz (hadd ne oldjam meg helyetted ;) ) de talán segít:
IFS=':' ; cat /etc/passwd | while read -a a ; do echo "---" $a "---" ; for i in "${a[@]}" ; do echo "." $i ; done ; done
Lényeg, hogy IFS-ben meg kell adni, mi legyen a mező szeparátor, a read -a tömbbe olvassa az egyes sorokat, a for ... in "${tomb[@]}" meg végigmegy az egyes tömbelemeken.
Esetedben az első elem a [0] lesz, ezt valahogyan el kellene távolítani a tömbből, mielőtt for-ral végigmész rajta, de arra már nem emlékszem, hogy azt hogy kell. Talán pop? Rég volt, én sem emlékszem.
- A hozzászóláshoz be kell jelentkezni