Pipe to mv-Befehl

Ich versuche, Dateien vom Terminal zu verschieben, aber nur die aus den Ergebnissen einer grepAbfrage.

ls -l | grep -i s02 | mv

Wie vervollständige ich den obigen Befehl am besten?

Wohin möchten Sie die Dateien verschieben?

Antworten (2)

Sie können dies erreichen, indem Sie einfach laufen

cd directory/containing/the/files
mv *[sS]02* /path/to/target/

Für komplexere Operationen gibt es auch die Option, findalle relevanten Dateien zu finden. Das Beispiel aus Ihrer Frage könnte auch geschrieben werden als

cd directory/containing/the/files
find . -type f -maxdepth 1 -iname '*s02*' -exec mv {} /path/to/target/directory/ \;

Es lohnt sich, einen Blick auf zu werfen, man findum zu sehen, welche anderen Optionen verfügbar sind.

Vor einiger Zeit hat mir jemand gesagt, dass reguläre Ausdrücke Strings abgleichen und Globs Dateinamen abgleichen/erzeugen. Eventuell kann man 3 glob helfen.

Zum Beispiel mit bash. Angesichts der folgenden Dateien

$ ls -1
test1
test2
test3

1) Um Überraschungen zu vermeiden, werfen wir zunächst einen Blick auf die Befehle

$ for i in test*; do echo mv $i $i.ext; done
mv test1 test1.ext
mv test2 test2.ext
mv test3 test3.ext

und die Befehle ausführen, wenn wir dies wollen

$ for i in test*; do mv $i $i.ext; done
$ ls -1
test1.ext
test2.ext
test3.ext

Passen Sie den Pfad an Ihre Bedürfnisse an.

2) Es ist möglich, sed und xargs zu verwenden . Testen wir es zuerst

$ ls -1 test* | sed 'p;s/test/test_/' | xargs -n2 printf "%s %s\n"
test2 test_2
test1 test_1
test3 test_3

und die Befehle ausführen, wenn wir dies wollen

$ ls -1 test* | sed 'p;s/test/test_/' | xargs -n2 mv
$ ls -1
test_1
test_2
test_3

Leerzeichen im Dateinamen

Diese Skripte funktionieren nicht wie erwartet, wenn die Dateinamen Leerzeichen enthalten. In Unix wird Leerzeichen als Trennzeichen verwendet. Zum Beispiel mit den Dateien

$ ls -1
test 1
test 2
test 3

Es ist klar, dass die folgenden Befehle nicht wie erwartet funktionieren können

$ for i in test*; do echo mv $i $i.ext; done
mv test 1 test 1.ext
mv test 2 test 2.ext
mv test 3 test 3.ext

Die Lösung besteht darin, das Leerzeichen aus der Liste der Trennzeichen auszuschließen

$ IFS="`printf '\n\t'`"

und stellen Sie es den Befehlen voran, die die Dateinamen mit Leerzeichen verarbeiten sollen. Der Befehl unten

$ IFS="`printf '\n\t'`"; for i in test*; do mv $i $i.ext; done

funktioniert wie erwartet

$ ls -1
test 1.ext
test 2.ext
test 3.ext

Die nächste Option ist das Zitieren der Argumente

for i in test*; do mv "$i" "$i.ext"; done

Auf diese Weise ist es möglich, die Vielfalt der Unix-Filter zu nutzen und die Beschränkung auf das Konstrukt "find ... -exec ... {}" zu umgehen. Weitere Einschränkungen finden Sie in den Hinweisen unter der Zeile.

Hinweise zu macOS

1) Zitat von opengroup.org - Produktstandard: Befehle und Dienstprogramme V4

1.4.21 sh
Frage 31: Wird die Umgebungsvariable IFS beim Aufruf der Shell ignoriert?
Antwort: Ja
Begründung: Die Spezifikation lässt zu, dass der Befehl sh die Einstellung der IFS-Umgebungsvariablen beim Aufruf ignoriert. Die Einstellung dieser Variablen wurde verwendet, um die Sicherheit auf Systemen zu verletzen, die die Shell verwenden, um einen Aufruf an die Schnittstellen system() und execvp() zu interpretieren.
Referenz: Technischer Standard, Shell and Utilities, Ausgabe 6, Kapitel 4, Utilities, sh, ENVIRONMENT VARIABLES, IFS.

2) Zitieren von developer.apple.com - Shell Input und Output

Sie können das Verhalten des Lesebefehls ändern, indem Sie die Shell-Variable IFS (kurz für interne Feldtrennzeichen) ändern. Das Standardverhalten besteht darin, Eingaben überall dort aufzuteilen, wo ein Leerzeichen, ein Tabulator oder ein Zeilenumbruch vorhanden ist. Durch Ändern dieser Variable ...

3) Zitieren von developer.apple.com - Basic Control Statements - Standard for Loops

Im nächsten Beispiel ist die Liste *.JPG ...

#!/bin/sh
for i in *.JPG ; do
    mv "$i" "$(echo $i | sed 's/\.JPG$/.x/')"
    mv "$(echo $i | sed 's/\.JPG$/.x/')" "$(echo $i | sed 's/\.JPG$/.jpg/')"
done


Diese Skripts funktionieren möglicherweise nicht wie erwartet, wenn der Dateiname Sonderzeichen enthält. Ersetzen Sie solche Zeichen zuerst. Siehe So entfernen Sie Sonderzeichen . Es gibt Dutzende von Artikeln zum Umbenennen von Dateien mit Leerzeichen und anderen Zeichen, die Probleme verursachen , z . Es ist eine gute Idee, solche Zeichen zu entfernen und die Dateinamen in das von Ihnen bevorzugte Format zu übersetzen (z. B. rename-file ), bevor Sie sie in *nix verarbeiten. Siehe Korrigieren von Unix/Linux/POSIX-Dateinamen .

Dies schlägt bei Dateinamen like test 1und similar fehl. Es wird auch nicht das tun, was Sie erwarten, wenn das aktuelle Verzeichnis Dateien enthält, deren Namen mit beginnen test.
Eine Umbenennung ist nicht erforderlich, stellen Sie sicher, dass Sie Optionen/Werkzeuge verwenden, die sicherstellen, dass \0Zeichenfolgen mit -terminiert sind, und sich um das Setzen/Verwenden von Variablen kümmern. Siehe mywiki.wooledge.org/BashPitfalls und mywiki.wooledge.org/BashFAQ :-)
Nun, IMHO ist es sicherer, effizienter und flexibler, pathologische Dateinamen loszuwerden und sich nicht um die Fallstricke zu kümmern, dh die Dateinamen so schnell wie möglich zu normalisieren und sie später zu verarbeiten. Sicherheit und Modularität sind alles was man braucht.
Danke für die Links, aber vielleicht sollten sich die Leute darauf konzentrieren, zu lernen, wie ein System funktioniert und nicht, wie es falsch ist. Wenn Shell-Skripte oder Programme bei Dateinamen brechen, die Zeichen enthalten, die das Dateisystem (und der Standard) zulässt, sind diese Skripte/Programme einfach gebrochen und müssen repariert werden.
Ich habe absolut keine Ahnung, worauf sich die Leute konzentrieren sollten. Fühlen Sie sich frei, rename-file zu testen und Probleme zu melden .
@VladimirBotka Ich arbeite hauptsächlich mit macOS, daher sind Leerzeichen in Dateinamen eine normale und häufige Sache. Ich würde argumentieren, dass sie überall dort üblich sind, wo Dateien hauptsächlich über eine GUI und nicht über eine Befehlszeile erstellt/verwendet werden.
Im Laufe der Jahre habe ich festgestellt, dass Menschen tun, was erlaubt ist, nicht was Sinn macht, wenn es um Computer geht. Da Unix ein Leerzeichen in einer Datei zulässt, ist es am besten, für das Leerzeichen zu codieren. Wikipedia nimmt macOS in seine Liste der Unix-Derivate auf. Apples sagte, macOS sei auf felsenfestem Unix aufgebaut.
@Gordon Davisson: Die Frage ist mit "Unix" gekennzeichnet, daher ist die Antwort nicht "macOS" spezifisch. Ich habe den Abschnitt zur Verarbeitung von Dateinamen mit Leerzeichen hinzugefügt. Sie haben Recht, dass solche Dateinamen üblich sind, aber das ist kein Grund, die Leerzeichen in die Dateinamen einzufügen, wenn ich es nicht muss. Leerzeichen in Dateinamen sind der andere Teil der Welt, der von MS geschaffen wurde. Niemand in der *nix-Welt würde es jemals freiwillig verwenden, was aus Wahrscheinlich zu spät für ein völliges Verbot von Leerzeichen in Dateinamen hervorgeht .
@Vladimir Botka Wo ist die Dokumentation?
@historystamp: Wir widersprechen uns nicht. Ja, die Leute können tun, was erlaubt ist. Ich kann es nicht verhindern, wenn ihm jemand ins Bein schießen will. Ja, es ist am besten, das Leerzeichen zu codieren. Trotzdem bevorzuge ich es, Leerzeichen hauptsächlich aus Sicherheitsgründen zu vermeiden. Ja, macOS ist ein UNIX-Derivat. Es gibt viele Unterschiede zwischen Unix-Derivaten. Zögern Sie nicht, es richtig zu markieren. (Ich frage mich, was der Grund sein könnte, solch offensichtlichen Unsinn wie Leerzeichen in den Dateinamen zu verteidigen. Was ist der Vorteil, ein Leerzeichen im Dateinamen anstelle von beispielsweise einem Unterstrich zu haben?)
@VladimirBotka Leerzeichen in Dateinamen stimmen mit der natürlichen Sprache überein und sind älter als Unix, sodass es sich nicht um eine MS-Sache handelt. Wenn Ihre Werkzeuge Räume unsicher machen, dann haben Sie grundsätzlich schlechte Werkzeuge. Verwenden Sie ein ;anständiges; Skriptsprache, z. B. AppleScript VB, Python, Perl, TCL-Schema usw., kein Porr wie sh usw.
@Mark: Guter Punkt, dass du sh erwähnt hast . Es ist die gemeinsame Shell zwischen den Systemen, und Ansible hat beschlossen, sie mit über 1000 Modulen , einschließlich iosxr_*-Modulen , zur Standard-Shell für plattformübergreifendes Systemmanagement zu machen . Ein System, das sehr wahrscheinlich einer der Gründe war, warum IBM RH für 34 Milliarden Dollar kaufte. Seien Sie nicht falsch, Sie wollen die gleichen schlechten Werkzeuge wie ich verwenden.
Es tut mir leid zu sagen, dass die Lösung für die Leerzeichenprobleme nicht darin besteht, den Wert von IFS zu ändern. Die Lösung besteht darin, keinefor Schleife über das Ergebnis von zu verwenden find. Die Verwendung find ... -exec(kombiniert mit xargsund/oder sh -c) ist die kanonische Unix-Methode, um solche Dinge zu tun.
Es gibt keinen "kanonischen Unix-Weg". Vielleicht ist es für macOS. Das Unix-Paradigma lautet: "Tools, Not Policy!" Übrigens. das ist der Unterschied, über den wir von Anfang an sprechen.