Gibt es eine Shopt Glob-Einstellung oder eine Einstellungskombination, die sich wie tcsh verhält?


7

Ich wechsle von einem langjährigen tcsh-Benutzer zu einem neuen Bash-Benutzer (es ist weit überfällig). Ich habe regelmäßig viele foreach-Schleifen in tcsh on the fly geschrieben, daher habe ich die Syntax für Bashs für Schleifen als Ersatz gelernt, war aber überrascht, als nicht übereinstimmende Glob-Muster als wörtliche Zeichenfolgen durch die Schleife geleitet wurden. Ich suchte nach einer Möglichkeit, dieses Verhalten so zu ändern, dass wörtliche Zeichenfolgen übersprungen und gefunden werden shopt -s nullglob. Mein Verständnis war, dass dies theoretisch dem Verhalten von tcsh entsprechen sollte, aber heute habe ich einen Unterschied entdeckt. Wenn ich das tue ls ../*.doesnotmatch, war das Ergebnis eine Liste des Inhalts des aktuellen Verzeichnisses. Insbesondere habe ich dies getan:

Bash:

$ shopt -s nullglob
$ ls ../*.sam
extractSplitReads_BwaMem    extractSplitReads_BwaMem.xml
$ shopt -u nullglob
$ ls ../*.sam
ls: ../*.sam: No such file or directory

Es gibt nichts im übergeordneten Verzeichnis, was übereinstimmt *.sam, insbesondere nicht das aktuelle Verzeichnis. Zuerst war ich wirklich verwirrt, aber dann wurde mir klar, dass das Glob-Muster verschwindet und der Befehl ausgeführt wurde, als hätte ich keine Argumente angegeben, z.

$ ls

Also habe ich versucht, Failglob sowohl für sich als auch mit Nullglob zu setzen, aber solange Failglob gesetzt ist, bricht jedes nicht übereinstimmende Glob-Muster den Befehl ab, unabhängig davon, ob ein übereinstimmendes Muster vorhanden ist oder nicht:

Bash:

$ shopt -s failglob
$ shopt -s nullglob
$ ls ../vis*/*.xml
../visualization/LAJ.xml
$ ls ../vis*/*.xml ../*.sam
bash: no match: ../*.sam
$ ls ../{vis*/*.xml,*.sam}
bash: no match: ../*.sam

Wenn ich tcsh verwende, werden alle Globs auf die übereinstimmenden Elemente reduziert. Wenn nichts übereinstimmt, wird ein Glob-Fehler angezeigt:

tcsh:

$ ls ../vis*/*.xml ../*.sam
../visualization/LAJ.xml
$ ls ../{vis*/*.xml,*.sam}
../visualization/LAJ.xml
$ ls ../*.sam
ls: No match.

Ich habe die Shopt-Einstellungen durchgesehen, sehe aber keinen Weg, um dieses Verhalten zu erreichen. Vermisse ich etwas Gibt es neben bash oder tcsh noch eine andere moderne Shell, die Globs so behandelt wie tcsh? Ich möchte das Verhalten von nullglob, wenn etwas übereinstimmt, aber das Verhalten von failglob, wenn nichts übereinstimmt, wie tcsh anscheinend funktioniert.


Direkt zu zshstatt zu gehen bashwäre ein viel natürlicherer Übergang. zshGlobs funktionieren bash -O failglobstandardmäßig wie , aber Sie können die cshnullglobOption verwenden, damit sie sich wie verhält tcsh. Siehe auch Warum ist nullglob nicht standardmäßig?
Stéphane Chazelas

Antworten:


4

Die einzigen shoptOptionen im Zusammenhang mit Dateinamen Expansion sind dotglob, failglob, nocaseglobund nullglob, und keiner von ihnen (allein oder kombiniert) scheint genau das zu tun , was Sie wollen. Es ist eine Schande, denn das klingt nach einer wirklich guten Idee.

Meine Empfehlung ist, failglobin interaktiven Sitzungen festgelegt zu haben, damit Sie potenziell unerwünschte Befehle vermeiden können, wie z.

mv -r file1 file2 dir1 dir2 destination-*-dir

wo file1, file2und dir1würde verschoben werden, dir2wenn destination-*-dirnichts übereinstimmt und nullglobgesetzt ist.

Auf der anderen Seite ist es keine gute Idee, sich beim Shell-Scripting vollständig auf Dateinamenerweiterungen zu verlassen. Es ist empfehlenswert, immer zu überprüfen, ob solche Erweiterungen vorhanden sind und wie sie sein sollen.

Ich meine, anstatt dies zu tun:

rm -- *.jpg *.txt

Es ist besser, so etwas zu tun:

for file in *.jpg *.txt; do
  if [ -f "${file}" ]; then
    rm -- "${file}"
  fi
done

# Or this (non-POSIX, as it uses an array)

for file in *.jpg *.txt; do
  if [ -f "${file}" ]; then
    files_to_delete+=( "${file}" )
  fi
done

if [ "${#files_to_delete[@]}" -gt 0 ]; then
  rm -- "${files_to_delete[@]}"
fi

Auf diese Weise sind Sie sicher, auch wenn beispielsweise einige Dateien übereinstimmen *.txt, es sich jedoch tatsächlich um ein Verzeichnis handelt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.