Ich habe ein kleines Bash-Skript geschrieben, um festzustellen, ob ein Verzeichnis mit dem Namen anaconda
oder miniconda
in meinem Benutzer $HOME
. Aber es findet das miniconda2
Verzeichnis in meinem Haus nicht.
Wie könnte ich das beheben?
if [ -d "$HOME"/"(ana|mini)conda[0-9]?" ]; then
echo "miniconda directory is found in your $HOME"
else
echo "anaconda/miniconda is not found in your $HOME"
fi
PS: Wenn [ -d "$HOME"/miniconda2 ]; then
ja, dann findet es das miniconda2-Verzeichnis, also denke ich, dass der Fehler im Teil liegt"(ana|mini)conda[0-9]?"
Ich möchte, dass das Skript allgemein ist. Für mich ist es miniconda2, aber für andere Benutzer ist es möglicherweise anaconda2, miniconda3 und so weiter.
command-line
bash
scripts
Jenny
quelle
quelle
Antworten:
Dies ist eine überraschend knifflige Sache.
Grundsätzlich
-d
wird nur ein einziges Argument getestet - auch wenn Sie Dateinamen mit einem regulären Ausdruck abgleichen könnten.Eine Möglichkeit wäre, das Problem umzudrehen und Verzeichnisse auf eine Regex-Übereinstimmung zu testen, anstatt die Regex-Übereinstimmung für Verzeichnisse zu testen. Mit anderen Worten, durchlaufen Sie alle Verzeichnisse
$HOME
mit einem einfachen Shell-Glob und testen Sie jedes mit Ihrer Regex, brechen Sie eine Übereinstimmung ab und testen Sie schließlich, ob dasBASH_REMATCH
Array nicht leer ist:Eine alternative Möglichkeit wäre, anstelle des regulären Ausdrucks einen erweiterten Shell-Glob zu verwenden und alle Glob-Übereinstimmungen in einem Array zu erfassen. Testen Sie dann, ob das Array nicht leer ist:
Durch das Trailing wird
/
sichergestellt, dass nur Verzeichnisse abgeglichen werden. dienullglob
verhindern , dass die Shell die unerreichte Zeichenfolge im Fall von Null Spielen von der Rückkehr.Um entweder rekursiv zu machen, setzen Sie die
globstar
Shell-Option (shopt -s globstar
) und dann jeweils:(Regex-Version):
for d in "$HOME"/**/; do
(erweiterte glob version):
dirs=( "$HOME"/**/@(ana|mini)conda?([0-9])/ )
quelle
?([0-9])
anstelle von@(|[0-9])
-?(...)
Null oder Eins verwenden, genau wie beim Regex-?
Quantifizierer.~/{ana,mini}conda{0..9}*/
mini
oderanaconda
installiert ist$HOME/sub-directories
? Zum Beispiel$HOME/sub-dir1/sub-dir2/miniconda2
globstar
In der Tat ist dies, wie bereits erwähnt, schwierig. Mein Ansatz ist der folgende:
find
und sein Regex- Funktionen, um die fraglichen Verzeichnisse zu finden.find
einx
für jedes gefundene Verzeichnis druckenx
es in einer ZeichenfolgeSomit:
Erläuterung:
find $HOME -maxdepth 1
findet alles unten$HOME
, beschränkt aber die Suche auf eine Ebene (dh, es wird nicht in Unterverzeichnisse rekursiv).-type d
schränkt die Suche auf nur eind
Schränkt Branchen ein-regextype egrep
gibt an, mitfind
welcher Art von regulären Ausdrücken wir es zu tun haben. Dies ist notwendig, weil Dinge wie[0-9]?
und(…|…)
etwas Besonderes sind undfind
diese standardmäßig nicht erkennen.-regex "$HOME/(ana|mini)conda[0-9]?"
ist der eigentliche reguläre Ausdruck wir Ausschau halten möchten-printf 'x'
druckt nur einex
für alles, was die vorherigen Bedingungen erfüllt.quelle
-bash: -regex: command not found found one of the directories
printf
. Wenn ich beispielsweise das Skript ausführe, wird es in Ordnung ausgeführt, aber der Befehl printf wird nicht gefunden, wenn es keine Übereinstimmung gibt, aber ich denke, es liegt daran, dass möglicherweise nichts zu drucken ist.-bash: -printf: command not found no match.
-printf
ist kein Befehl, sondern ein Argument fürfind
. Das macht der Backslash am Ende der vorherigen Zeile.-quit
, den gefundenen Pfad nach dem Drucken zu drucken, es sei denn, Sie möchten weiterhin Unklarheiten feststellen.x
stattdessen zu verwenden:foundDir=$(find $HOME -maxdepth 1 -type d -regextype egrep -regex "$HOME/(ana|mini)conda[0-9]?" -print -quit); echo "found $foundDir"
Sie können eine Liste der zu testenden Verzeichnisnamen durchlaufen und darauf reagieren, wenn einer von ihnen vorhanden ist:
Diese Lösung lässt offensichtlich nicht die volle Regex-Kraft zu, aber die Shell-Globbing- und Klammer-Expansion ist zumindest in dem von Ihnen gezeigten Fall gleich. Die Schleife wird beendet, sobald ein Verzeichnis vorhanden ist, und die zuvor festgelegte Variable wird gelöscht
a
. In der folgendenecho
Zeile wird die Parametererweiterung${a+not }
auf "nichts" erweitert, wenna
gesetzt (= kein Verzeichnis gefunden) und "nicht".quelle
Mögliche Problemumgehung besteht darin, Miniconda und Anaconda wie unten gezeigt getrennt zu suchen
Aber wenn jemand Vorschläge hat, würde ich gerne wissen, warum wir bei der Suche nach Verzeichnissen keine Regex übergeben können.
quelle
shopt -s nullglob; dirs=( "$HOME"/miniconda* "$HOME"/anaconda* ); if (( ${#dirs[@]} > 0 )); then ...
] || [
mit-o
sollte es zumindest nicht brechen , wenn beiden Verzeichnisse gefunden werden , da beide Verzeichnis Klackse für im gleichen Test betreut werden.