W przypadku plików w katalogu wyświetla się tylko echo nazwy pliku (bez ścieżki)


99

W jaki sposób mogę wyświetlić tylko nazwę pliku, jeśli iteruję katalog z pętlą for?

for filename in /home/user/*
do
  echo $filename
done;

ściągnie pełną ścieżkę z nazwą pliku. Chcę tylko nazwę pliku.

Odpowiedzi:


166

Jeśli chcesz mieć natywne bashrozwiązanie

for file in /home/user/*; do
  echo "${file##*/}"
done

Powyższe wykorzystuje rozszerzenie parametrów, które jest natywne dla powłoki i nie wymaga wywołania zewnętrznego pliku binarnego, takiego jakbasename

Mogę jednak zasugerować użycie find

find /home/user -type f -printf "%f\n"

9
Dobra odpowiedź. Dla tych, którzy chcą dowiedzieć się więcej o rozszerzaniu parametrów: wiki.bash-hackers.org/syntax/pe#substring_removal
DougW

1
-printf: nieznany główny lub operator => unix.stackexchange.com/a/272493/72893
Nobita

2
Rozważ zmianę ${file##*/}na, "${file##*/}"aby obsługiwać nazwy plików ze spacjami, np. „Moja nazwa pliku ze spacjami.txt”.
WinEunuuchs2Unix

echo "$ {file ## * /}" zwraca pusty ciąg
Alessandro C

48

Po prostu użyj basename:

echo `basename "$filename"`

Cudzysłowy są potrzebne w przypadku, gdy $ filename zawiera np. Spacje.


3
lepiej używać rozszerzania parametrów, nie wymaga wywołań zewnętrznych plików binarnych.
SiegeX

5
Btw, `` jest przestarzałe. Lepiej używać $()tak, jak zrobił to Oli
SiegeX

1
Przepraszamy za komentarz do tej starej odpowiedzi, ale basename nie będzie działać poprawnie dla plików ze spacją. Przykład: moc PWD: /test 1, basename $(pwd)Wydajność: test. Przetestowano na OS X i Ubuntu Server (14.04). Natywne rozwiązanie bash, zgodnie z zaleceniami @SiegeX, działa dla mnie.
Marko Grešak

@ MarkoGrešak Użyj basename "$(pwd)"zamiast tego.
YoungFrog

@YoungFrog dzięki za wkład, ale to było 9 miesięcy temu. Byłoby też lepiej użyć zmiennej $PWDzamiast uruchamiać polecenie.
Marko Grešak

16

Zastosowanie basename:

echo $(basename /foo/bar/stuff)

Dlaczego używasz echo? basenamejuż drukuje wyniki. echomoże nawet zmienić wynik, jeśli nie zacytujesz podpowłoki. Przykład: echo $(basename path/with\ \ spaces)niepoprawne drukowanie with spaces(tylko jedna spacja).
Socowi

8

Innym podejściem jest użycie lspodczas czytania listy plików w katalogu, aby uzyskać to, czego chcesz, tj. „Tylko nazwy plików”. W przeciwieństwie do odczytywania pełnej ścieżki pliku, a następnie wyodrębniania składnika „nazwa pliku” w treści pętli for.

Poniższy przykład zgodny z oryginałem:

for filename in $(ls /home/user/)
do
  echo $filename
done;

Jeśli uruchamiasz skrypt w tym samym katalogu, w którym znajdują się pliki, staje się on po prostu:

for filename in $(ls)
do
  echo $filename
done;

1
lszawiera wszystkie pliki dotfile, których *rozszerzenie zwykle nie obejmuje. for f in $(...) ...Niepowodzenie również, jeśli jakakolwiek nazwa pliku zawiera białe znaki, chyba że ustawisz IFS, może się nie powieść, jeśli jakakolwiek nazwa pliku zawiera znak globalny, chyba że ustawisz -f / -o noglob, aw zależności od systemu lub powłoki echomoże się nie powieść, jeśli nazwa pliku jest łącznikiem + litera lub zawiera ukośnik odwrotny. OTOH ls -1 /path/to/dirsam z siebie niezawodnie drukuje każdą nazwę pliku w linii, modulo różnicę plików dot.
dave_thompson_085

0

jeśli chcesz tylko nazwę pliku:

for file in /home/user/*; do       
  f=$(echo "${file##*/}");
  filename=$(echo $f| cut  -d'.' -f 1); #file has extension, it return only filename
  echo $filename
done

Więcej informacji na temat cutpolecenia można znaleźć tutaj .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.