Wyjście „find” względem katalogu

34

Chciałbym użyć, findaby wyświetlić listę wszystkich plików i katalogów rekurencyjnie w danym katalogu głównym dla cpiooperacji. Nie chcę jednak, aby sam katalog główny pojawiał się na ścieżkach. Na przykład obecnie otrzymuję:

$ find diskimg
diskimg
diskimg/file1
diskimg/dir1
diskimg/dir1/file2

Ale chciałbym dostać

file1
dir1
dir1/file2

(zwróć uwagę, że root nie znajduje się również w moich pożądanych wynikach, ale łatwo się go pozbyć tail).

Korzystam z systemu OS X i wolałbym nie instalować żadnych dodatkowych narzędzi (np. GNU find), jeśli to możliwe, ponieważ chciałbym udostępnić skrypt, który piszę innym użytkownikom systemu OS X.

Wiem, że można to zrobić, cutaby odciąć katalog główny, ale wydaje się to nieoptymalne rozwiązanie. Czy jest dostępne lepsze rozwiązanie?

nneonneo
źródło
find diskimg/* | cut -d '/' -f2-
nik.shornikov

Odpowiedzi:

18

Jeśli to, co próbujesz zrobić, nie jest zbyt skomplikowane, możesz to zrobić za pomocą sed:

find diskimg | sed -n 's|^diskimg/||p'

Lub cut:

find diskimg | cut -sd / -f 2-
BriGuy
źródło
możesz wybrać (prawie) dowolny separator dla polecenia, więc: find diskimg | grep -v '^diskimg$' | sed -e 's|^diskimg/||'(zauważ, że dodałem również „-e” i ^równie dobrą praktykę (tutaj nie jest to konieczne, ponieważ jesteś pewien, że każda linia będzie miała to ... ale nadal dobrą praktykę , i oszczędza trochę procesora;))
Olivier Dulac
inny sposób bez grep: find diskimg | sed -e 's|^diskimg/*||' („/ *” będzie pasować do dowolnej liczby „/”, nawet 0)
Olivier Dulac
To cutpolecenie jest czystsze niż to, którego użyłem; Lubię to. ( sedRozwiązanie jest również miłe, ale powtórzenie diskimg/jest trochę niefortunne).
nneonneo,
30

cd najpierw do katalogu:

cd diskimg && find . 

Po zakończeniu wrócisz do katalogu głównego.

W tym przypadku twoje pliki zostaną uzupełnione ./; jedynym sposobem, w jaki widzę, byłoby użycie cut:

{ cd diskimg && find .; } | tail -n +2 | cut -c 3-

Użyj podpowłoki, aby uniknąć zmiany bieżącego katalogu powłoki (nie jest to konieczne, jeśli wysyłasz dane wyjściowe, ponieważ lewa strona potoku działa już w podpowłoce).

(cd diskimg && find .)
Stephan
źródło
5
być z powrotem w oryginalnym katalogu po zakończeniu: dodać nawias: (cd diskimg && find . ; ). W ten sposób cd diskimg && find .odbywa się to w podpowłoce: po wyjściu z tej podpowrotki powracasz do swojej własnej powłoki, niezależnie od tego, gdzie byłeś.
Olivier Dulac,
1
find *jest innym sposobem na obejście bezużytecznego prefiksu
nik.shornikov
23

Kolejna, bardziej złożona, ale wykorzystująca podejście find z mojej innej odpowiedzi:

find diskimg -mindepth 1 -printf '%P\n'
Stephan
źródło
Nie wszystkie wersje findwsparcia printf.
jordanm,
1
Pewno; Wygląda na to, że mój OSX nie. Częściowo dlatego zaproponowałem inne rozwiązanie.
Stephan
2
@Stephan - następnym razem możesz po prostu połączyć te typy odpowiedzi w jedną. Nie ma potrzeby udzielania wielu odpowiedzi w przypadku takich wariancji.
slm
2
findObsługuje tylko GNU -printf, podczas gdy wiele BSD findskopiowało niektóre funkcje GNU find, żadne jeszcze nie skopiowało -printf(AFAIK).
Stéphane Chazelas,
%Pna ścieżkę względną co było mi potrzebne.
Fl0v0
4

Użyj realpathnarzędzia:

find diskimg -exec realpath --relative-to diskimg {} \;
dwjbosman
źródło
Zgrabne - dzięki za pokazanie mi --relative-to.
nneonneo