Iterowanie po każdym wierszu wyjścia ls -l

120

Chcę iterować po każdym wierszu w danych wyjściowych: ls -l /some/dir/*

Teraz próbuję: for x in $(ls -l $1); do echo $x; done

Jednak to iteruje po każdym elemencie w linii osobno, więc otrzymuję:

-r--r-----
1
ivanevf
eng
1074
Apr
22
13:07
File1

-r--r-----
1
ivanevf
eng
1074
Apr
22
13:17
File2

Ale chcę powtórzyć każdą linię jako całość. W jaki sposób mogę to zrobić?

Ivan
źródło
1
Zawsze cytuj zmienne (i dane wyjściowe polecenia), chyba że masz ku temu konkretny powód.
glenn jackman

Odpowiedzi:

247

Ustaw IFS na nowy wiersz, na przykład:

IFS='
'
for x in `ls -l $1`; do echo $x; done

Umieść wokół niego podpowłokę, jeśli nie chcesz ustawiać IFS na stałe:

(IFS='
'
for x in `ls -l $1`; do echo $x; done)

Lub użyj while | czytaj zamiast tego:

ls -l $1 | while read x; do echo $x; done

Jeszcze jedna opcja, która uruchamia while / read na tym samym poziomie powłoki:

while read x; do echo $x; done << EOF
$(ls -l $1)
EOF
Randy Proctor
źródło
12
Uważaj, gdy potokujesz do while, while będzie działać w podpowłoce, co oznacza, że ​​nie może zmieniać zmiennych w głównym procesie
Reorx
1
Co tu robi 1 dolar? Muszę użyć tego w skrypcie, który piszę, który akceptuje argumenty. 1 $ wyrzuca rzeczy. Co mogę włożyć zamiast 1 $, aby uzyskać ten sam efekt? Chciałbym skorzystać z drugiego rozwiązania.
noob-in-need
@ noob-in-need Zastąp go dowolnym katalogiem, który chcesz wyświetlić
vpzomtrrfrt
1
Możesz to zrobić, read -rbo inaczej bash usunie z danych niezaciągane odwrotne ukośniki.
Brian Gordon
6

To zależy, co chcesz zrobić z każdą linią. awk jest użytecznym narzędziem do tego typu przetwarzania. Przykład:

 ls -l | awk '{print $9, $5}'

.. w moim systemie wyświetla nazwę i rozmiar każdej pozycji w katalogu.

Adam Holmberg
źródło
3

Jak już wspomniano, awk jest do tego odpowiednim narzędziem. Jeśli nie chcesz używać awk, zamiast analizować wyjście „ls -l” wiersz po wierszu, możesz iterować po wszystkich plikach i wykonać „ls -l” dla każdego pojedynczego pliku w następujący sposób:

for x in * ; do echo `ls -ld $x` ; done
Axel
źródło
3

Możesz także wypróbować findpolecenie. Jeśli chcesz tylko pliki w bieżącym katalogu:

find . -d 1 -prune -ls

Uruchomić polecenie na każdym z nich?

find . -d 1 -prune -exec echo {} \;

Policz linie, ale tylko w plikach?

find . -d 1 -prune -type f -exec wc -l {} \;

David Koski
źródło
znalezisko jest zepsute. Często pojawiają się dziwne komunikaty o błędach. chce mi pomóc, gdy linia poleceń jest całkowicie poprawna i wydaje się, że gdy zacznie to robić, nie zatrzyma się do następnego ponownego uruchomienia MOŻE. czasami wydaje się przypadkowe, jeśli chodzi o błędy. nie wiem, jak mogę zgłosić błąd.
Jim Michaels
1

Narzędzie read (1) wraz z przekierowaniem wyjścia polecenia ls (1) zrobi, co chcesz.

Steve Emmerson
źródło
-1

Dlaczego więc nikt nie zasugerował po prostu użycia opcji eliminujących części, których nie chce przetwarzać.

Na nowoczesnym Debianie po prostu otrzymujesz plik z:

ls --format=single-column 

Co więcej, nie musisz zwracać uwagi na to, w jakim katalogu go uruchomisz, jeśli używasz pełnego katalogu:

ls --format=single-column /root/dir/starting/point/to/target/dir/

To ostatnie polecenie używam powyższego i otrzymuję następujący wynik:

bot@dev:~/downloaded/Daily# ls --format=single-column /home/bot/downloaded/Daily/*.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141119_IENT1.txt.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141120_IENT1.txt.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141121_IENT1.txt.gz
BradChesney79
źródło