L'approccio di @ meuh è inefficiente in quanto il suo -maxdepth 1
approccio consente ancora di find
leggere il contenuto delle directory al livello 1 per ignorarle successivamente. Inoltre non funzionerà correttamente con alcune find
implementazioni (incluso GNU find
) se alcuni nomi di directory contengono sequenze di byte che non formano caratteri validi nelle impostazioni locali dell'utente (come per i nomi di file con una codifica di caratteri diversa).
find . \( -name . -o -prune \) -extra-conditions-and-actions
è il modo più canonico di implementare GNU -maxdepth 1
(o FreeBSD -depth -2
).
In genere, però, è -depth 1
tu che vuoi ( -mindepth 1 -maxdepth 1
) come non vuoi considerare .
(profondità 0), e poi è ancora più semplice:
find . ! -name . -prune -extra-conditions-and-actions
Perché -maxdepth 2
diventa:
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Ed è qui che corri nei problemi con i personaggi non validi.
Ad esempio, se hai una directory chiamata Stéphane
ma é
codificata nel set di caratteri iso8859-1 (aka latin1) (0xe9 byte) come era più comune in Europa occidentale e in America fino alla metà degli anni 2000, allora quel byte 0xe9 non è un carattere valido in UTF-8. Quindi, nelle versioni locali UTF-8, il *
carattere jolly (con alcune find
implementazioni) non corrisponderà Stéphane
poiché *
è 0 o più caratteri e 0xe9 non è un carattere.
$ locale charmap
UTF-8
$ find . -maxdepth 2
.
./St?phane
./St?phane/Chazelas
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
$ find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St?phane/Chazelas/age
./St?phane/Chazelas/gender
./St?phane/Chazelas/address
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
Il mio find
(quando l'uscita va su un terminale) visualizza quel byte 0xe9 non valido come ?
sopra. Potete vedere che St<0xe9>phane/Chazelas
non era prune
d.
Puoi aggirare il problema facendo:
LC_ALL=C find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Tuttavia, ciò influisce su tutte le impostazioni locali find
e su qualsiasi applicazione in esecuzione (come tramite i -exec
predicati).
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
Ora, ho davvero un -maxdepth 2
ma nota come l'é nel secondo Stéphane correttamente codificato in UTF-8 viene visualizzato come ??
byte 0xc3 0xa9 (considerati come due singoli caratteri indefiniti nella locale C) della codifica UTF-8 di é caratteri non stampabili nella locale C.
E se avessi aggiunto un -name '????????'
, avrei ottenuto Stéphane sbagliato (quello codificato in iso8859-1).
Per applicare a percorsi arbitrari invece di .
, devi fare:
find some/dir/. ! -name . -prune ...
per -mindepth 1 -maxdepth 1
o:
find some/dir/. \( ! -path '*/./*/*' -o -prune \) ...
per -maxdepth 2
.
Vorrei ancora fare un:
(cd -P -- "$dir" && find . ...)
In primo luogo perché ciò rende i percorsi più brevi, il che rende meno probabile che si verifichino percorsi troppo lunghi o che elenchi problemi troppo lunghi , ma anche per aggirare il fatto che find
non può supportare argomenti di percorso arbitrari (tranne -f
con FreeBSD find
) in quanto si soffocano valori di $dir
like !
o -print
...
In -o
combinazione con la negazione è un trucco comune per eseguire due serie indipendenti di -condition
/ -action
in find
.
Se si desidera eseguire -action1
su riunioni di file -condition1
e indipendentemente -action2
su riunioni di file -condition2
, non è possibile eseguire:
find . -condition1 -action1 -condition2 -action2
Come -action2
verrebbe eseguito solo per i file che soddisfano entrambe le condizioni.
Né:
find . -contition1 -action1 -o -condition2 -action2
Come -action2
non verrebbe eseguito per i file che soddisfano entrambe le condizioni.
find . \( ! -condition1 -o -action1 \) -condition2 -action2
funziona come \( ! -condition1 -o -action1 \)
risolverebbe vero per ogni file. Questo presuppone -action1
è un'azione (come -prune
, -exec ... {} +
) che restituisce sempre vero . Per azioni del genere -exec ... \;
può sembrare falso , potresti voler aggiungere un altro -o -something
dove -something
è innocuo ma restituisce vero come -true
in GNU find
o -links +0
o -name '*'
(anche se nota il problema relativo ai caratteri non validi sopra).
-depth -2
,-depth 1
... potrebbe essere visto come migliore di GNU-maxdepth
/-mindepth