Wynik normalnego znalezienia przy użyciu find . ! -path "./build*" -name "*.txt"
:
./tool/001-sub.txt
./tool/000-main.txt
./zo/001-int.txt
./zo/id/002-and.txt
./as/002-mod.txt
a po sortowaniu według sort -n
:
./as/002-mod.txt
./tool/000-main.txt
./tool/001-sub.txt
./zo/001-int.txt
./zo/id/002-and.txt
jednak pożądanym wynikiem jest:
./tool/000-main.txt
./zo/001-int.txt
./tool/001-sub.txt
./zo/id/002-and.txt
./as/002-mod.txt
co oznacza, że dane wyjściowe są sortowane tylko na podstawie nazw plików , ale informacje o folderach powinny być przechowywane jako część danych wyjściowych.
Edycja : Spraw, aby przykład był bardziej skomplikowany, ponieważ struktura podkatalogów może obejmować więcej niż jeden poziom.
-printf
zamiastawk
), myślę, że to najlepsze rozwiązanie. Przerobiłem moją pierwotną implementację, aby używać tej metody.Odpowiedzi:
Musisz posortować według ostatniego pola (traktowanego
/
jako separator pól). Niestety nie mogę wymyślić narzędzia, które może to zrobić, gdy liczba pól jest różna (jeśli tylkosort -k
może przyjąć wartości ujemne).Aby obejść ten problem, musisz wykonać dekorację-sortowanie-undecorate. Oznacza to, że weź nazwę pliku i umieść go na początku, a następnie separator pól, a następnie wykonaj sortowanie, a następnie usuń pierwszą kolumnę i separator pól.
To
awk
polecenie mówi, że separator pólFS
jest ustawiony na/
; wpływa to na sposób odczytywania pól. Separatora pole wyświetlaniaOFS
jest również ustawiony/
; wpływa to na sposób drukowania rekordów. Następna instrukcja mówi, że wypisz ostatnią kolumnę (NF
to liczba pól w rekordzie, więc jest to również indeks ostatniego pola), a także cały rekord ($0
jest to cały rekord); wydrukuje je z OFS między nimi. Następnie lista jestsort
edytowana, traktując ją/
jako separator pól - ponieważ w pliku mamy najpierw nazwę pliku, sortuje się według niej. Następniecut
drukuje tylko pola 2 do końca, ponownie traktując/
jako separator pól.źródło
-printf '%f/%p\n'
Używałbym plików „-printf” do wypisania nazwy i ścieżki, sortowania według nazwy i odcięcia nazwy w ostatnim kroku. „###” to tylko marker ułatwiający cięcie.
% f drukuje nazwę pliku,% p całą ścieżkę.
Uprościłem polecenie find, aby umieścić je w jednej linii, oczywiście, że opuścisz tę
! -path "./build*"
część.źródło
W zsh ≥4,3.10:
**/*.txt
dopasowuje rekursywnie*.txt
do bieżącego katalogu i jego podkatalogów .~build*
nie obejmuje dopasowań, których tekst zaczyna się odbuild*
(jak! -path './build*'
). (Potrzebujeszsetopt extended_glob
najpierw.)(oe\''…'\')
jest globalnym kwalifikatorem sortującym .REPLY=…
konstruuje ciąg do sortowania od ciągu do zwrócenia.${REPLY:t}
to basename („ogon”) ścieżki.źródło