Używam następującego kodu do skonfigurowania azmienna zawierająca serię różnych nazw plików, które następnie wykonam po kilku funkcjach. Zaangażowane pliki znajdują się w innym katalogu (DIRECTORY
) do katalogu, w którym kod jest wykonywany (CURRENT_DIRECTORY
). Myślałem, że poniższy kod może zostać użyty do zmiany katalogu zawierającego pliki cd $DIRECTORY
, zapisz listę plików w zmiennej $FILES
a następnie powróć do oryginalnego katalogu (cd $CURRENT_DIRECTORY
) gdzie można wykonać resztę kodu. Jeśli jednak wykonam dwa polecenia echa, pierwsze zawiera listę plików, gdy jestem w katalogu, w którym przechowywane są pliki, ale drugie polecenie echa właśnie drukuje "vclist_2d_*.txt"
, tzn. interpretuje to jako ciąg znaków, a nie listę plików (prawdopodobnie dlatego, że zmieniłam z powrotem na oryginalny katalog i dlatego nie może znaleźć żadnych plików, które pasują vclist_2d_*.txt
). Dlaczego tak się dzieje i jak mogę obejść ten problem (bez uruchamiania wszystkiego w tym samym katalogu)?
#!/bin/bash
CURRENT_DIRECTORY=`pwd`
DIRECTORY=/home/Documents/NewDirectory/
cd $DIRECTORY
pwd
FILES=vclist_2d_*.txt
echo $FILES
cd $CURRENT_DIRECTORY
echo $FILES
Odpowiedzi:
4 dla odpowiedzi № 1Musisz zapisać wynik ekspansji globu.
Globs nie są rozszerzane w prostych przypisaniach zmiennych, więc twój bieżący kod rozszerza glob, gdy ty echo
to (dlatego dostajesz zachowanie, które widzisz). Próbować echo "$FILES"
i na przykład w ogóle się nie rozszerzy.
Przypisanie do tablic rozszerza się jednak tak FILES=(vclist_2d_*.txt)
spowoduje natychmiastowe rozwinięcie globu, a następnie użycie echo "${FILES[@]}"
później będzie działać poprawnie.
1 dla odpowiedzi nr 2
FILES=vclist_2d_*.txt
nie jest rozszerzany przez powłokę. FILES
teraz zawiera ciąg vclist_2d_*.txt
.
echo $FILES
wysyła echo vclist_2d_*.txt
do skorupy. Powłoka następnie rozszerza wzorzec, co skutkuje A) łańcuchem vclist_2d_*.txt
jeśli wzorzec nie pasuje do niczego, lub B) lista pasujących nazw plików.
Następnie zmień katalog i powtórz proces. W żadnym punkcie nie ma listy plików przypisanych do żadnej zmiennej.
Teraz ty mógłby przypisz wydajność z echo vclist_2d_*.txt
do zmiennej (SOMEVAR=$(echo vclist_2d_*.txt)
, ale to rozwiązałoby twój problem tylko w połowie. Jak zamierzasz „działać na każdym pliku na liście”? Jeśli myślisz o for file in $SOMEVAR
, zastanów się, co by się stało, gdyby nazwa pliku zawierała spację ...
Najłatwiejszym i najbardziej niezawodnym rozwiązaniem jest użycie find
zamiast:
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} +
To skutkuje do_something
przekazał listę pasujących plików. Jeśli lista jest bardzo długo może być podzielony na wiele wywołań do_something
.
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} ;
To skutkuje do_something
wywoływany dla każdego pasującego pliku.
Jeśli jest szansa, że twój obecny katalog może zawierać pliki pasujące do wzorca przekazanego do find
powyżej, musisz uciec od gwiazdki (dodając cytaty tak jak ja lub uciekając przez nią) *
) aby uniknąć rozszerzenia powłoki, zmieniając twoje find
polecenie do czegoś innego.