/ / Ustawianie zmiennych powłoki tak, aby zawierały listy plików - bash, shell

Ustawianie zmiennych powłoki w celu przechowywania list plików - bash, shell

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 № 1

Musisz 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.