Ich versuche, ein Skript zu schreiben, das Leerzeichen durch "-" ersetzt und alle Buchstaben für alle Dateien im aktuellen Verzeichnis in Kleinbuchstaben schreibt.
for x in 'ls'
do
if [ ! -f $x ]; then
continue
fi
lc = `echo $x | tr '[A-Z]' '[a-z]'`
if [ $lc != $x ]; then
mv $x $lc
fi
done
find -name "* *" -type f | rename 's/ /-/g'
Ich erhalte folgende Ausgabe: call: umbenennen von in Dateien ...
Die Namen ändern sich jedoch nicht, Beispiel: 252680610243-Analyzed Sample2 2Jul12.txt
Ich habe die Berechtigungen mit geändert chmod 706
. Würde dies das Problem verursachen? Was fehlt mir hier?
Hier ist die Ausgabe von bash -x lower.sh
:
+ for x in ''\''ls'\'''
+ '[' '!' -f ls ']'
+ continue
+ find -name '* *' -type f
+ rename 's/ /-/g'
call: rename from to files...
mv
und wirfst einecho $lc
oder zwei ein, damit du sehen kannst, was du tust, und arbeitest dann von dort aus? Siehe auchbash -x
: tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html Das Erlernen des Fischens ist besser als nach Fisch zu fragen;)mv...
durchecho $lc
die Ausgabe des Codes nicht veränderte.`ls`
nicht'ls'
- oder noch besser, nurfor x in *
. Mein Punkt über die Echos und Sachen war, dass Sie die Ausgabe jedes Befehls berücksichtigen sollten (z. B.for x in 'ls'
ist überhaupt nicht das, was Sie denken, dass es ist).Unexpected arguments passed on cmd line ./lower.sh: line 8: [: !=: unary operator expected
Antworten:
Bei Debian und Derivaten (einschließlich Ubuntu) ist dies mit einem einfachen Aufruf an
rename
:Sie haben
rename
jedoch ein anderes Dienstprogramm mit demselben Namen .quelle
Es gibt verschiedene Probleme mit Ihrem Skript.
Sie durchlaufen eine Liste mit einem Wort :
ls
. Sie`ls`
wollten wahrscheinlich schreiben (mit Backticks), um die Ausgabe von zu analysierenls
. Analysieren Sie nicht die Ausgabe vonls
: Dies funktioniert nicht, wenn die Dateinamen Sonderzeichen wie Leerzeichen enthalten. Die Shell verfügt bereits über eine integrierte Methode zum Auflisten der Dateien in einem Verzeichnis: Platzhalter. Also schreibefor x in *
.Dies funktioniert nicht, wenn der Dateiname Leerzeichen und andere Sonderzeichen enthält. Wenn Sie
$x
externe Anführungszeichen schreiben , wird das Ergebnis in separate Wörter aufgeteilt (und jedes Wort wird zum Booten als Platzhaltermuster interpretiert). Um diesen Effekt zu vermeiden, setzen Sie$x
doppelte Anführungszeichen :if [ ! -f "$x" ]; then
. Sie können sich an komplexe Regeln erinnern oder einfach immer doppelte Anführungszeichen für Variablensubstitutionen verwenden.Einige andere Zeilen sind aufgrund fehlender doppelter Anführungszeichen unterbrochen. Setzen Sie sie einfach um jede variable Substitution.
Dies funktioniert aufgrund der Leerzeichen um das Gleichheitszeichen nicht: Diese Zeile führt den
lc
Befehl aus und übergibt ihn=
als erstes Argument (und andere Argumente). Eine Zuweisung in der Shell darf kein Leerzeichen um das=
Zeichen haben.Sie brauchen keine Klammern um die Argumente von
tr
. Hier funktioniert der Befehl zufällig, weil Sie sagen, dass Sie[
nach[
und]
nach]
zusätzlich zum Kleinbuchstaben ersetzen sollen .Ich empfehle die Verwendung von Dollar-Klammern
$(…)
anstelle von Backticks`…`
für die Befehlsersetzung. Sie sind äquivalent, außer dass Backticks komplexe Regeln für das Zitieren von Dingen enthalten, während$(…)
sie eine sehr intuitive Syntax haben. Alles in allem sollte dieser Befehl lauten:lc=$(echo "$x" | tr A-Z a-z)
Ihre Fehlermeldung zeigt an, dass Sie den
rename
Befehl aus dem util-linux-Paket haben und nicht das Perl-Skript, das unter Debian und Derivaten (einschließlich Ubuntu) gefunden wurde. Die von Ihnen verwendete Syntax ist nur mit dem Perl-Skript sinnvoll.Wenn Sie das Perl-Skript verwenden, kann es die Groß- und Kleinschreibung in Kleinbuchstaben ändern, sodass Sie dies nicht vorher tun müssen. Und Sie müssen nicht aufrufen, es
find
sei denn, Sie möchten Dateien auch in Unterverzeichnissen umbenennen (was in Ihrem ersten Teil nicht behandelt wird). Wenn Sie alle Dateien im aktuellen Verzeichnis umbenennen möchten, können Sie einfach schreiben:Wenn Sie nur reguläre Dateien umbenennen möchten (jedoch keine Unterverzeichnisse, symbolischen Links usw.), verwenden Sie
find
:Wenn Sie auch auf Dateien in Unterverzeichnissen reagieren möchten und die Verzeichnisnamen Leerzeichen oder Großbuchstaben enthalten können, müssen Sie darauf achten, diese in Ruhe zu lassen. Da Sie unter Linux arbeiten, können Sie mit einem Argument
-execdir
aufrufenprename
, das keinen Verzeichnisnamen enthält.Was ist, wenn Sie das Perl-
rename
Dienstprogramm nicht haben ? Das Dienstprogramm util-linuxrename
hilft Ihnen hier nicht weiter. Sie können einen weiteren Ersatz in Ihre Schleife einfügen.Mit bash müssen Sie nicht aufrufen
tr
, sondern können die String-Substitutionskonstrukte verwenden.Wenn Sie auch auf Dateien in Unterverzeichnissen reagieren möchten, können Sie einen rekursiven Glob verwenden (aktiviert durch die
globstar
Option). Achten Sie auch hier darauf, den Verzeichnisteil in Ruhe zu lassen, wenn er Großbuchstaben oder Leerzeichen enthalten kann.Geben Sie in zsh
autoload -U zmv
your ein.zshrc
, und Sie können daszmv
mit dem Glob-Qualifikationsmerkmal verwenden.
, um nur reguläre Dateien und Parametererweiterungskonstrukte für die Umbenennung abzugleichen:So bearbeiten Sie auch Dateien in Unterverzeichnissen:
quelle
find -exec prename
müssen Sie nur das übersetzenbasename
, sonst funktioniert das nicht richtig, wenn einige Dirnamen Großbuchstaben enthalten. Nicht alle Lösungen verhalten sich für Nicht-ASCII-Buchstaben gleich.-maxdepth 1
da das ursprüngliche Skript in der Frage rekursiv war, aber ich habe es vergessen. Die Antwort ist lang genug, ich halte mich an ASCII-Buchstaben wie die Frage.tr
die erforderlich[...]
, so kann man schreiben möchte kann estr '[A-Z]' '[a-z]'
Tragbarkeit zu verbessern (als zusätzliche[
,]
nicht schaden für den BSD / POSIX-Stiltr
).Das Hauptproblem ist, dass Sie nicht über Ihre Dateien iterieren: Sie iterieren über eine einzelne Zeichenfolge
"ls"
. Sie wollten wahrscheinlich Backticks anstelle von einfachen Anführungszeichen verwenden. Trotzdem nicht analysierenls
.Sie müssen auch Ihre Variablen zitieren, insbesondere da Sie wissen, dass sie Leerzeichen enthalten.
Nur in Bash können Sie dies tun:
quelle
Möglicherweise haben Sie Probleme mit dem Befehl "mv" und Leerzeichen. Ich habe die Originaldatei in doppelte Anführungszeichen gesetzt.
Dieses Skript hat bei mir funktioniert.
quelle
In Bash 4 konvertiert $ {var ,,} var in Kleinbuchstaben:
quelle