Jak wyprowadzać tylko nazwy plików (ze spacjami) w ls -Al?

78

Powinienem powtarzać tylko nazwy plików lub katalogów o tej konstrukcji:

ls -Al | while read string
do
...
done

ls -Al wynik :

drwxr-xr-x  12 s162103  studs         12 march 28 12:49 personal domain
drwxr-xr-x   2 s162103  studs          3 march 28 22:32 public_html
drwxr-xr-x   7 s162103  studs          8 march 28 13:59 WebApplication1

Na przykład, jeśli spróbuję:

ls -Al | while read string
do
echo "$string" | awk '{print $9}
done

następnie wypisuj tylko pliki i katalogi bez spacji. Jeśli plik lub katalog ma spacje takie jak „domena osobista”, będzie to tylko słowo „osobisty”.

Potrzebuję bardzo prostego rozwiązania. Może jest lepsze rozwiązanie niż awk.

Alex Zern
źródło
2
Dlaczego nie tylko ls -Al *' '*? Wynik parsowania lsnigdy nie prowadzi do niczego dobrego.
manatwork
1
Jeśli potrzebujesz czegoś, co zadziała w dowolnym * nix, unikaj używania ls -Al | while. Prostym i bardziej niezawodnym sposobem jest for string in *; do echo "$string"; done.
forcefsck
Potrzebuję tylko z tą konstrukcją. OK, nie proste, każde rozwiązanie!
Alex Zern
1
Dlaczego potrzebne ls ? Analiza lsi „działa w całości * nix i nie zepsuje się, jeśli coś się stanie”, nie idą dobrze razem.
terdon

Odpowiedzi:

97

Ty naprawdę nie powinien analizować dane wyjściowels . Jeśli jest to zadanie domowe i wymaga tego Twój profesor, nie wie o czym mówi. Dlaczego nie zrobisz czegoś takiego:

Dobry ...

find ./  -printf "%f\n"

lub

for n in *; do printf '%s\n' "$n"; done

...Źli...

Jeśli naprawdę chcesz używać ls, możesz uczynić go trochę bardziej niezawodnym, wykonując coś takiego:

ls -lA | awk -F':[0-9]* ' '/:/{print $2}'

... i brzydkie

Jeśli nalegasz , aby zrobić to w niewłaściwy, niebezpieczny sposób i po prostu musisz użyć whilepętli, wykonaj następujące czynności:

ls -Al | while IFS= read -r string; do echo "$string" | 
    awk -F':[0-9]* ' '/:/{print $2}'; done

Poważnie, ale nie rób tego.

terdon
źródło
drwx------ 2 s162103 studs 3 oct. 9 2012 .ssh drwxr-xr-x 3 s162103 studs 6 oct. 25 09:02 .subversion drwxrwxrwt 3 s162103 studs 3 nov. 15 2012 .TempoItemsczasami mam randkę bez czasu, tylko rok i
gapię się
1
@AlexZern Cóż, to jeden z powodów, dla których nie analizujesz wyników ls.
terdon
2
@AlexZern, po co ci ten -lprzełącznik? Jeśli wszystko czego potrzebujesz to nazwy plików, po prostu uruchom ls -A. Używanie -ltylko utrudnia życie, ponieważ teraz trzeba przeanalizować wyniki.
terdon
ponieważ potrzebuję dodatkowych informacji, takich jak dostęp, data, właściciel itp. Napisałem ogromny skrypt, który działa dobrze, z wyjątkiem nazw plików do drukowania i katalogów ze spacjami.
Alex Zern
3
OK. Mamy tutaj problem XY . lsto po prostu nie najlepszy sposób na uzyskanie tego, czego potrzebujesz. Dlaczego nie opublikujesz nowego pytania wyjaśniającego informacje, które chcesz zebrać, a my możemy zasugerować, jak to zrobić. Alternatywnie możesz użyć skryptu w obecnej postaci i skorzystać z jednej z powyższych sugestii, aby wydrukować tylko nazwę. Ale poważnie, nie analizuj ls, po prostu powiedz nam dokładnie, co próbujesz zrobić w nowym pytaniu.
terdon
74

Czy jest jakiś powód, dla którego ls -A1* nie działa?

Na przykład:

$ touch file1 file2 file\ with\ spaces
$ ls -Al
total 0
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file1
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file2
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file with spaces
$ ls -A1
file1
file2
file with spaces
$

* Uwaga: to wielka litera A i numer jeden.

bahamat
źródło
4
-1 jest genialny. Nie wiedziałem, że jest dostępny. (Wiem, wiem, RTFM.)
The Lazy Coder
który działa tylko w bieżącym katalogu, jeśli chcesz wyświetlić listę nazw plików z innego katalogu, powiedz ~ / projects, wtedy otrzymasz pełne ścieżki zamiast nazw plików
thecotne
@ thecotne na Mac 10.9.5 wyświetla tylko nazwy plików. Z jakiego systemu operacyjnego korzystasz?
AJP,
uruchamiam to ls ~ / projects / *. sublime-project -A1 for ls ~ / projects -A1 dostaję tylko nazwy
thecotne
3
@ TheLazyCoder nie powinien czytać instrukcji.
c24w
41

Zastanawiam się, dlaczego nikt nie wspomniał o tym prostym poleceniu:

ls -a | sort
Ben
źródło
2
Znakomity! Masz pojęcie, w jaki sposób sortpotokowanie powoduje, że blok wielokolumnowy jest niepodzielny na jedną kolumnę?
msciwoj
@msciwoj po prostu bierze ciągi znaków oddzielone białymi spacjami i drukuje je posortowane oddzielone liniami końcowymi
Ben
DOSKONAŁY! Dlaczego nie został on oznaczony jako prawdziwa odpowiedź !?
夏 期 劇場
3
Działa tutaj, ponieważ lspowraca do ls -1(wyjście z pojedynczą kolumną), gdy jego wyjście nie trafia do terminala (i wyłącza cytowanie / zamianę niedrukowalnych znaków; @Kusalananda, jeśli lsnie jest zgodne z POSIX, jeśli nadal tak jest). lsdane wyjściowe są już posortowane. Więc potokowanie go do sortco najwyżej nic nie zrobi, a co gorsza zniekształci dane wyjściowe (jeśli nazwy plików zawierają znaki nowego wiersza) lub zawiedzie dla nazw plików, które nie są tekstem. ls -a | catbyłoby lepiej. Lub nawet lepiej, ls -A1jak już wspomniano (i ponieważ generalnie chcesz
zamieniać
1
@ StéphaneChazelas Noted. lszachowuje się inaczej, gdy wyjście nie jest terminalem.
Kusalananda
3

Nie można przeanalizować wyniku ls, nie mówiąc już o tym, ls -lponieważ znak nowej linii, podobnie jak spacja, jest tak samo poprawnym znakiem, jak każdy znak w nazwie pliku. Musisz także wziąć pod uwagę dowiązania symboliczne, które mają dane wyjściowe podobne ... foo -> bar.

Dlaczego miałbyś użyć -lmimo wszystko, jeśli chcesz tylko nazwę pliku?

Po prostu zrób:

for file in *; do
  ...
done

Jeśli chcesz dołączyć pliki kropek (oprócz .i ..), w zależności od powłoki:

zsh:

for file in *(ND); do
  ...
done

bash:

shopt -s nullglob dotglob
for file in *; do
  ...
done

ksh93:

FIGNORE='@(.|..)'
for file in ~(N)*; do
  ...
done

POSIXly:

for file in .[!.]* ..?* *; do
  [ -e "$file" ] || [ -L "$file" ] || continue
  ...
done
Stéphane Chazelas
źródło
1

Co powiesz na:

for file in * .[!.]*
do
  printf "%s\n" "$file"
done
Skrutator
źródło
1
ls -Al | tr -s ' ' | cut -f9- -d' '

skompresuj wiele spacji do pojedynczych spacji za pomocą tr, a następnie możesz użyć wycięcia do podziału na polach

simpleuser
źródło
-1
ls --file *|grep ^ 

wyświetla jakie pliki w jakim katalogu.

Vars
źródło
Nie sądzę, że to rozwiązuje pytanie.
Jeff Schaller