Używam find do wszystkich plików w katalogu, więc otrzymuję listę ścieżek. Potrzebuję jednak tylko nazw plików. tzn. dostaję ./dir1/dir2/file.txt
i chcę dostaćfile.txt
266
W GNU find
możesz do tego użyć -printf
parametru, np .:
find /dir1 -type f -printf "%f\n"
-o
Ma niższy priorytet niż sugerowany-a
, więc często będziesz chciał pogrupować swoje-o
argumenty)Jeśli twoje wyszukiwanie nie ma opcji -printf, możesz także użyć basename:
źródło
... {} ';'
Użyj,
-execdir
która automatycznie przechowuje bieżący plik{}
, na przykład:Możesz także użyć
$PWD
zamiast.
(w niektórych systemach nie będzie generować dodatkowej kropki z przodu).Jeśli nadal masz dodatkową kropkę, możesz uruchomić:
Jeśli zostanie użyty
+
zamiast;
, to{}
zostanie zastąpiony jak największą liczbą ścieżek dla każdego wywołania narzędzia. Innymi słowy, wypisze wszystkie nazwy plików w jednym wierszu.źródło
./filename
zamiastfilename
. W zależności od potrzeb może być lub nie być w porządku.$PWD
zamiast.
.Jeśli używasz GNU find
Lub możesz użyć języka programowania, takiego jak Ruby (1.9+)
Jeśli masz ochotę na bash (co najmniej 4) rozwiązanie
źródło
Jeśli chcesz uruchomić jakieś działanie tylko przeciwko nazwie pliku, użycie
basename
może być trudne.Na przykład to:
po prostu wyśle echo basename
/my/found/path
. Nie to, co chcemy, jeśli chcemy wykonać na nazwie pliku.Ale możesz wtedy uzyskać
xargs
wynik. na przykład, aby zabić pliki w katalogu na podstawie nazw w innym katalogu:źródło
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \;
Na Mac (BSD
find
) użyj:źródło
-exec
i-execdir
są powolne,xargs
jest królem.xargs
Równoległość pomaga również.Co zabawne, nie potrafię wyjaśnić ostatniego przypadku
xargs
bez-n1
. Daje poprawny wynik i jest najszybszy¯\_(ツ)_/¯
(
basename
pobiera tylko 1 argument ścieżki, alexargs
wyśle je wszystkie (właściwie 5000) bez-n1
. nie działa na systemie Linux i openbsd, tylko macOS ...)Niektóre większe liczby z systemu Linux, aby zobaczyć, jak
-execdir
pomaga, ale wciąż znacznie wolniej niż równoleglexargs
:źródło
find
jest to-execdir
, że staje się najszybciej jak tworzenie nowych procesów jest stosunkowo kosztowna operacja.Szczerze
basename
idirname
rozwiązania są łatwiejsze, ale można też to sprawdzić:lub
lub
źródło
Jak zauważyli inni, możesz łączyć
find
ibasename
, ale domyślniebasename
program będzie działał tylko na jednej ścieżce na raz, więc plik wykonywalny będzie musiał zostać uruchomiony raz dla każdej ścieżki (przy użyciu jednegofind ... -exec
lub dwóchfind ... | xargs -n 1
), co może być potencjalnie wolne.Jeśli użyjesz tej
-a
opcjibasename
, może zaakceptować wiele nazw plików w jednym wywołaniu, co oznacza, że możesz użyćxargs
bez-n 1
, aby pogrupować ścieżki w znacznie mniejszą liczbę wywołańbasename
, co powinno być bardziej wydajne.Przykład:
Tutaj umieściłem
-print0
i-0
(które powinny być używane razem), aby poradzić sobie z dowolnymi spacjami w nazwach plików i katalogów.Oto porównanie czasowe między wersjami
xargs basename -a
ixargs -n1 basename
. (Ze względu na porównanie typu „tak jak z podobnym” podane tutaj czasy są po początkowym manekinie, więc oba są wykonywane po skopiowaniu metadanych pliku do pamięci podręcznej we / wy.) Przesłałem dane wyjściowe docksum
w obu przypadkach tylko w celu wykazania, że dane wyjściowe są niezależne od zastosowanej metody.Jak widać, naprawdę jest znacznie szybsze, aby uniknąć uruchamiania za
basename
każdym razem.źródło
basename
akceptuje wiele nazw plików bez potrzeby stosowania dodatkowych argumentów wiersza polecenia. Wykorzystanie-a
tutaj jest w systemie Linux. (basename --version
mówi mibasename (GNU coreutils) 8.28
.)Znalazłem rozwiązanie (na stronie makandracards), które podaje tylko najnowszą nazwę pliku:
(podziękowania dla Arne Hartherz)
Użyłem go do
cp
:źródło