Ich verwende zsh unter Linux unter setopt extended_glob ksh_glob glob_dots
. Ich suche nach etwas, das einfach über die Befehlszeile ohne Portabilitätsanforderungen eingegeben werden kann. Ich betrachte einen Quellcodebaum ohne „seltsame“ Dateinamen (z. B. nein \
in Dateinamen, kein Dateiname beginnend mit -
).
Mit einem der folgenden Befehle wird die Liste der Unterverzeichnisse des aktuellen Verzeichnisses rekursiv gedruckt:
find -type d
print -l **/*/
Dies ist eigentlich eine SVN-Kasse:
$ find -type d
./.deps
./.svn
./.svn/text-base
./.svn/prop-base
./.svn/tmp
./.svn/tmp/text-base
./.svn/tmp/prop-base
./.svn/tmp/props
./.svn/props
./lib/.svn
./lib/.svn/text-base
./lib/.svn/prop-base
./lib/.svn/tmp
./lib/.svn/tmp/text-base
./lib/.svn/tmp/prop-base
./lib/.svn/tmp/props
./src/.svn
./src/.svn/text-base
./src/.svn/prop-base
./src/.svn/tmp
./src/.svn/tmp/text-base
./src/.svn/tmp/prop-base
./src/.svn/tmp/props
Ich möchte die .svn
Verzeichnisse und ihre Unterverzeichnisse ausschließen, die in jedem Verzeichnis vorhanden sind. Es ist einfach mit find
:
find -type d -name .svn -prune -o -print
Kann ich das mit einem kurzen zsh glob machen? Das Ignorieren von Punktdateien kommt nahe (ich muss es explizit tun, weil ich glob_dots
gesetzt habe):
print -l **/*(/^D)
Dies ist jedoch nicht zufriedenstellend, da es das .deps
Verzeichnis verbirgt , das ich sehen möchte. Ich kann die Pfade herausfiltern, die Folgendes enthalten .svn
:
print -l **/*~(*/|).svn(|/*)(/)
Aber das ist kaum kürzer als find
(also wofür benutze ich zsh?). Ich kann es verkürzen print -l **/*~*.svn*(/)
, aber das filtert auch aufgerufene Verzeichnisse heraus hello.svn
. Außerdem durchläuft zsh die .svn
Verzeichnisse, was bei NFS oder Cygwin etwas langsam ist.
Gibt es eine bequeme (wie einfach zu tippende) Möglichkeit, einen bestimmten Verzeichnisnamen (oder noch besser: ein beliebiges Muster) in einem rekursiven Glob auszuschließen?
printf '%s\n' **/*
oder zu schreibenprint -rl -- **/*
?Antworten:
Die erweiterten Glob-Operatoren von Zsh unterstützen Matching Over
/
(im Gegensatz zu Kshs sogar in der Implementierung von Zsh ). Zsh's**/
ist eine Abkürzung für(*/)#
(*/
0 oder mehrmals wiederholt). Alles was ich tun muss, ist das*
durch^.svn
(alles andere als.svn
) zu ersetzen .Ordentlich!
quelle
setopt EXTENDED_GLOB
. Ohne es wirst du bekommenzsh: bad pattern: [...]
.CMakeLists.txt
in verschiedenen Unterverzeichnissen verteilten Dateien abzugleichen, wobei alle Verzeichnisse, die mitcmake-*
der Suche beginnen, ausgeschlossen werden. Ich habe es versucht(^cmake-*)**/CMakeLists.txt#
; es funktioniert, aber es enthält nicht dasCMakeLists.txt
in meinem Arbeitsverzeichnis (dh es findet diejenigen, die sich ausschließlich in Unterverzeichnissen befinden ). Wie kann ich es aufnehmen? Danke und tolle Antwort!cmake-*
auf einer beliebigen Ebene ausschließen möchten, verwenden Sie wie in meiner Antwort(^cmake-*/)#CMakeLists.txt
. Wenn Sie nur ausschließen möchten,cmake-foo/bar/CMakeLists.txt
aber nichtbaz/cmake-qux/CMakeLists.txt
, benötigen Sie einen anderen Ansatz :**/CMakeLists.txt~cmake-*/*
.cmake-*
Ordner, die ich ausschließen wollte, befinden sich in meinem aktuellen Verzeichnis und ich wollte sie alle ausschließen. Ich habe Ihre erste Lösung ausprobiert und es hat funktioniert. Vielen Dank!Während
ksh93
Globbingzsh
auch mit derglobstar
Option bei weitem nicht annähernd möglich istksh93
, kann es erreicht werden mit:quelle