Nasledujúci kód používam na nastavenie apremenná obsahujúca sériu rôznych mien súborov, ktoré potom následne vykonám na niektorých funkciách. Príslušné súbory sa nachádzajú v inom adresári (DIRECTORY
) do adresára, kde sa kód vykonáva (CURRENT_DIRECTORY
). Myslel som si, že nasledujúci kód je možné použiť na zmenu do adresára obsahujúceho súbory cd $DIRECTORY
, uloží zoznam súborov do premennej $FILES
a potom sa vráťte späť do pôvodného adresára (cd $CURRENT_DIRECTORY
) kde je možné vykonať zvyšok kódu. Ak však urobím dva príkazy ozveny, prvý obsahuje zoznam súborov, keď sa nachádzam v adresári, kde sú uložené súbory, ale druhý príkaz echo iba vytlačí "vclist_2d_*.txt"
, tj. interpretuje to ako reťazec a nie ako zoznam súborov (pravdepodobne preto, že som sa zmenil späť do pôvodného adresára, a preto nemôže nájsť žiadne súbory, ktoré sa zhodujú vclist_2d_*.txt
). Prečo sa to stane a ako môžem vyriešiť tento problém (bez spustenia všetkého v rovnakom adresári)?
#!/bin/bash
CURRENT_DIRECTORY=`pwd`
DIRECTORY=/home/Documents/NewDirectory/
cd $DIRECTORY
pwd
FILES=vclist_2d_*.txt
echo $FILES
cd $CURRENT_DIRECTORY
echo $FILES
odpovede:
4 pre odpoveď č. 1Musíte si uložiť výsledok globálnej expanzie.
Globy sa nerozširujú v jednoduchých priradeniach premenných, takže váš súčasný kód rozširuje globus, keď vy echo
to (čo je dôvod, prečo dosiahnete správanie, ktoré vidíte). Vyskúšajte echo "$FILES"
a napríklad sa vôbec nerozšíri.
Priradenie k poliam sa však rozširuje FILES=(vclist_2d_*.txt)
okamžite rozšíri glob a potom použije echo "${FILES[@]}"
neskôr bude fungovať správne.
1 pre odpoveď č. 2
FILES=vclist_2d_*.txt
sa nerozbalí o shell. FILES
teraz obsahuje reťazec vclist_2d_*.txt
.
echo $FILES
odošle echo vclist_2d_*.txt
do ulity. Škrupina potom rozšíri vzor, výsledkom čoho je buď A) reťazec vclist_2d_*.txt
ak sa vzor nezhoduje s ničím, alebo B) zoznam zodpovedajúcich názvov súborov.
Potom zmeníte adresár a postup zopakujete. Zoznam súborov nie je v žiadnom okamihu priradený k žiadnej premennej.
Teraz ty mohol priradiť výkon z echo vclist_2d_*.txt
do premennej (SOMEVAR=$(echo vclist_2d_*.txt)
, ale to by váš problém vyriešilo iba do polovice. Ako zamýšľate „konať s každým súborom v zozname“? Ak uvažujete o a for file in $SOMEVAR
, zvážte, čo by sa stalo, keby názov súboru obsahoval medzeru ...
Najjednoduchším a najrobustnejším riešením je použitie find
miesto:
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} +
Výsledkom je do_something
prešiel zoznam zodpovedajúcich súborov. Ak je zoznam veľmi dlho, to môže byť rozdelené do niekoľkých hovorov z do_something
.
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} ;
Výsledkom je do_something
sa volá pre každý zhodný súbor.
Ak existuje šanca, že váš prúd adresár môže obsahovať súbory zodpovedajúce vzoru odovzdanému find
vyššie, musíte uniknúť z hviezdičky (pridaním úvodzoviek, ako som to urobil ja, alebo únikom cez *
) aby ste zabránili rozšíreniu shellu tým, že find
rozkaz do niečoho iného.