Wie verwendet man reguläre Ausdrücke mit dem Befehl cp unter Linux?

22

Ich versuche, nur eine Teilmenge von Dateien von einem Verzeichnis in ein anderes zu kopieren, werde cpjedoch mit der Nachricht begrüßt cp: cannot stat [^\.php]': No such file or directory. Gibt es eine Möglichkeit, reguläre Ausdrücke nur mit dem cpBefehl zu verwenden?

PeanutsMonkey
quelle

Antworten:

29

Nein.

Der cpBefehl kann keine seiner Argumente als reguläre Ausdrücke verarbeiten. Sogar Platzhalter werden von ihm (oder den meisten ausführbaren Dateien) nicht verarbeitet. Vielmehr werden sie von der Shell gehandhabt.

cp test/* test2/wird tatsächlich durch bash erweitert, und alles, was cpwirklich für seine Argumente cp test/file1 test/file2 test/file3 test2/spricht, ist (oder was auch immer angemessen ist, basierend auf dem tatsächlichen Inhalt von test/).

Ich glaube auch nicht, dass Ihr Ausdruck [^\.php]mit dem übereinstimmt, was Sie möchten (er stimmt nicht nur mit Dateien überein, die enthalten .php).

Sie möchten sich wahrscheinlich das findDienstprogramm ansehen , um eine Liste der Dateien basierend auf regulären Ausdrücken herauszufiltern und dann xargsdie zurückgegebene Dateiliste auf den cpBefehl anzuwenden (vorausgesetzt, find hat keinen eingebauten Handler zum Kopieren von Dateien; I ' Ich bin mit dem Werkzeug nicht vertraut.

Sie könnten versuchen:

find . ! -iregex ".*\.php.*" -exec cp {} /destination/folder/ \;

Dies besagt, dass das aktuelle Verzeichnis rekursiv nach Dateien durchsucht werden soll, die nicht ".php" im Pfad enthalten, und diese in das Verzeichnis kopiert werden sollen /destination/folder/.

Wie gewünscht, eine genauere Aufschlüsselung der Argumente:

  • . - Ort, an dem die Suche gestartet werden soll - in diesem Fall das aktuelle Verzeichnis
  • ! - Operator "Nicht" invertiert das Ergebnis des nächsten Tests
  • -iregex- Test auf reguläre Ausdrücke ohne Berücksichtigung der Groß- und Kleinschreibung. Das nächste Argument ist der Ausdruck.
  • ".*\.php.*"- Übereinstimmung mit regulären Ausdrücken <Anything>.php<Anything>- Jede Datei, die irgendwo im Pfad ".php" enthält. (Beachten Sie, dass Sie, auch wenn Sie sich in einem Ordner befinden, dessen Name ".php" enthält, einen komplexeren Ausdruck benötigen, um nur mit den Dateien übereinzustimmen.)
  • -exec- Führen Sie einen Befehl aus, wenn die vorhergehenden Tests true zurückgeben. Das nächste Argument ist der Befehl. Alle verbleibenden Argumente ;werden an den Befehl übergeben. das {}ist ein besonderes Argument , die die Dateinamen.
  • cp - Der Befehl "find" sollte für jeden übereinstimmenden Pfadnamen ausgeführt werden.
  • {}- Der Pfad zu der gefundenen Datei wird cpals Argument übergeben, damit bekannt ist, welche Datei kopiert werden soll
  • /destination/folder/- Argument, das an übergeben wird cpund angibt, cpwohin die Datei kopiert werden soll.
  • \;- Dies ist der ;Terminator, der -execgesucht wird. Wir schließen es mit einem, \damit Ihre Shell nicht versucht, es zu analysieren, sondern es stattdessen als Argument an den Befehl ( find) weiterleitet.

Es ist ziemlich schwierig , einen regulären Ausdruck zu schreiben , die „Strings , die nicht haben übereinstimmt .php“, so dass wir stattdessen sagen findfür Strings suchen , die sie enthalten , .phpmit und dann umkehren die Ergebnisse !.

Darth Android
quelle
2
find . -name [^\.php] -exec cp {} /path/to/location \;Vorsicht bei Dateien mit Sonderzeichen.
Rob
@Darth Android - Danke. Mir war das nicht bewusst cpund andere Binaries waren nicht in der Lage, reguläre Ausdrücke zu erweitern. Würde es Ihnen etwas ausmachen, die Bedeutung der Optionen und Argumente in dem von Ihnen angegebenen Beispiel zu erläutern? Ich weiß , dass .auf der aktuellen Verzeichnis verweist aber was !, {}, \;, etc. beziehen sich auf als auch , was sie bedeuten? Zum Beispiel, warum musst du dem entkommen ;?
PeanutsMonkey
@Rob - Was meinst du mit speziellen Dateien?
PeanutsMonkey
@Rob - Ich habe versucht, mithilfe eines ähnlichen Ausdrucks bestimmte Dateien zu entfernen. Dabei wurden jedoch alle Dateien im Verzeichnis gelöscht. Mein Befehl war find . -name '[^\.txt]' -exec rm {} \;daher meine Zurückhaltung find. Wahrscheinlich ein Fehler von meiner Seite, aber ich bin nicht sicher, was ich falsch gemacht habe. Soweit ich {}find . -name '[^\.txt]'
weiß
Was versuchst du mit dem Regex zusammenzubringen?
Rob
10

Sie können nur wenige andere Tools von der Konsole aus verwenden, z. B. grep und xargs.

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder
0xAF
quelle
Wie {}unterscheidet sich das von -t?
PeanutsMonkey
2
In diesem Fall nicht viel. Eine alternative Syntax für xargs wäre 'xargs cp {} destination_folder'. Die Standard-CP-Syntax verwendet am Ende eine oder mehrere Quellen und ein Ziel. Wenn Sie die Option -t verwenden, können Sie das Ziel nach dem -t angeben und dann den Rest der Zeile für Quellen verwenden. Ich finde die Option -t in diesem Fall einfach praktischer. Im anderen Beispiel wird das {} durch das ersetzt, was an xargs (stdin) weitergeleitet wird, in diesem Fall den Dateinamen.
0xAF
-1

Sie können den folgenden Befehl einfach ausführen:

find /home/usr/search_dir -iname *file_name_portion*.txt | xargs cp -t /home/usr/destination_folder

cool haa !!

Nisan Chhetri
quelle