Mehrere Dateien von Dateiname X nach Dateiname Y kopieren?


7

Ich möchte Dateien innerhalb eines lexikografischen Bereichs kopieren.

Beispiel für Dateien:

-rw-r--r--   1 root root   15276 Oct  5  2004 a2ps.cfg
-rw-r--r--   1 root root    2562 Oct  5  2004 a2ps-site.cfg
-rw-r--r--   4 root root    4096 Feb  2  2007 acpi.txt
-rw-r--r--   1 root root      48 Feb  8  2008 adjtime.jpg
-rw-r--r--   4 root root    4096 Feb  2  2007 alchemist.jpg

Anwendungsbeispiel:

  • Kopieren Sie die 3 Dateien von asps.cfgnachacpi.txt
  • Kopieren Sie die 3 Dateien von a2ps-site.cfgnachadjtime.jpg
  • Kopieren Sie die 4 Dateien von a2ps-site.cfgnachalchemist.jpg

Gibt es also eine Möglichkeit, eine Reihe von Dateien (von Dateiname X bis Dateiname Y) in ein Verzeichnis zu kopieren?

Mögen: cp filenameX ... filenameY destination/


Es wird spät hier ... aber es ist nicht klar, wie oder warum Sie 'cfg'-Dateien nach' jpg 'kopieren würden und warum Sie sagen, dass es' Bereiche 'gibt. Außerdem scheinen sie im Besitz von root zu sein. Wirst du das als root kopieren?

Ich denke, er bedeutet, alle Dateien von asps.cfg nach acpi.txt in einen Zielordner zu kopieren, oder zumindest habe ich das so interpretiert.

Die Dateien sind nur Beispiele, ich werde viele Bilder kopieren.

1
Ich denke, es wäre hilfreicher, wenn Ihr Beispiel Ihr tatsächlicher Anwendungsfall wäre. Derzeit ist es ziemlich schwierig zu bestimmen, was Sie tun müssen.
Steven D

Mein tatsächlicher Anwendungsfall ist ungefähr 200 Bilder, das wäre zu lang. Ich habe 5 Dateien verwendet, wenn es ausreicht, um zu zeigen, wonach ich suche. Was ich tun muss, sind die Anwendungsbeispiele in der Frage. Wenn Sie die Frage nicht verstehen, können Sie sie nicht beantworten;)
Tiax

Antworten:


4

Ein allgemeiner Ansatz besteht darin, eine Shell-Funktion zu definieren, die eine Reihe von Dateinamen druckt. In einer einfachen Version dieser Funktion werden alle Dateien zwischen zwei Dateinamen einschließlich im aktuellen Verzeichnis aufgelistet:

range()
{
    ls | sed -n "/^$1\$/,/^$2\$/p"
}

Hierbei wird ein sed-Bereich verwendet, um etwas zwischen den beiden angegebenen Zeichenfolgen ( $1und $2) auszudrucken .

Sie können diese Funktion dann in Ihrem cp(1)Befehl verwenden:

cp $(range asps.cfg acpi.txt) /destination/path

Dies schlägt fehl, wenn Sie Dateinamen mit Leerzeichen haben. Dafür müssen Sie etwas komplizierter werden:

range asps.cfg acpi.txt | xargs -d '\n' -I {} cp {} /destination/path

Dies schlägt fehl, wenn Ihre Dateinamen Zeilenumbrüche (\ n) enthalten. Das ist sehr unwahrscheinlich, daher bleibt das Reparieren eine Übung für den Leser.

Sie könnten das zusammen in eine andere Shell-Funktion rollen:

cprange()
{
    [ $# -eq 3 ] || { echo "usage: cprange start end dir" >&2; return 1;}
    range "$1" "$2" | xargs -d '\n' -I {} cp {} "$3"
}

und benutze es wie:

cprange filenameX filenameY destination

Denken Sie daran, dass der Bereich nur für Dateinamen im aktuellen Verzeichnis funktioniert. Sie können dies auf verschiedene Arten erweitern (zusätzliche Verzeichnisparameter range, Extrahieren eines Pfads aus Argumenten zur rangeVerwendung dirnameusw.), aber das überlasse ich Ihnen basierend auf Ihren Anforderungen. Bitte fragen Sie, ob Sie hier weitere Details wünschen.


Wie definiere ich den Funktionsbereich ()? Ich habe versucht, eine Datei mit dem Namen range.sh mit der darin enthaltenen Funktion zu erstellen, die dann ausgeführt wird ./range.sh, aber wenn ich versuche, sie zu verwenden, heißt es "-sh: range: Befehl nicht gefunden"
Tiax

Sie müssen die Datei als Quelle ausführen, anstatt sie auszuführen, damit sich die Funktion in Ihrer aktuellen Bash-Umgebung befindet. Wie:source range.sh
Steven D

Wenn es sich um eine Funktion handelt, die Sie möglicherweise häufig verwenden, fügen Sie sie in Ihre .bashrc-Datei ein. Andernfalls können Sie einfach ein Shell-Skript auf Ihrem Pfad erstellen und den Funktionsumbruch weglassen.
Camh

3

Zsh bietet eine einfache Möglichkeit, eine Reihe von Dateien aus dem Ergebnis eines Globs auszuwählen (ein Glob ist eine Platzhalterübereinstimmung). Auf der positiven Seite ist der Befehl sehr kurz zu schreiben. Auf der Minus-Site müssen Sie die Ordnungszahlen der Dateien herausfinden, die Sie schreiben möchten. Der folgende Befehl kopiert beispielsweise die 21., 22.,…, 40. Datei mit einer .jpgErweiterung im aktuellen Verzeichnis, wobei die Dateien in alphabetischer Reihenfolge aufgelistet sind:

cp *.jpg([21,40]) destination/

Zsh hat eine Option , die nicht hilfreich sein kann oder Sie da : unter setopt numeric_glob_sort, foo9bar.jpgwird vor dem sortiert werden foo10bar.jpg. Sie können auch eine andere Sortierreihenfolge in den Glob-Qualifikationsmerkmalen auswählen, z. B. cp *.jpg(om[21,40]) destination/um die 21. bis 40. neuesten Dateien auszuwählen (verwenden Sie ein Großbuchstaben O, um in der entgegengesetzten Reihenfolge zu sortieren). Weitere Informationen finden Sie unter Glob-Qualifikationsmerkmale im Handbuch.

Unter jeder Shell können Sie eine Schleife schreiben, die die Dateien durchläuft, mit dem Kopieren bei der ersten Datei beginnt, die Sie schreiben möchten, und nach der letzten Datei stoppt. Warnung, ungetestet.

in_range=
for x in *.jpg; do
  if [ "$x" = "first-file.jpg" ]; then in_range=1; fi
  if [ -n "$in_range" ]; then cp "$x" destination/; fi
  if [ "$x" = "last-file.jpg" ]; then break; fi
done

0

In diesem Beispiel ist es am einfachsten, M- * zu verwenden, um Ihr Muster zu vervollständigen und diejenigen zu entfernen, die Sie nicht kopieren möchten.

% cp *[hit Escape and press *]
->
% cp file1 file2 file3 file4 ... 

und dann einfach manuell die Dateien entfernen, die Sie nicht kopieren möchten. Wie auch immer, dies ist eine Shell-Funktion, keine cp.

Sie können das Muster beliebig verfeinern. Wenn Sie viele andere Dateien im Verzeichnis hatten und nur diejenigen kopieren möchten, die mit beginnen a, beginnen Sie das Muster einfach mit diesem Buchstaben. Möglicherweise möchten Sie die Dokumentation der Shell zum Dateinamen-Globbing nachschlagen. Zum Beispiel http://tldp.org/LDP/abs/html/globbingref.html .


Da es viele Bilder geben wird, ist dieser Weg zu kompliziert.

0

Es scheint, dass Dateinamen sortiert sind und Sie in gleichen Mengen verteilen.

Holen Sie sich alle Dateinamen in eine einzige Datei

ls > all_files

Teilen Sie die Datei in Stapel auf

split -l 4 all_files all_files-

Sie haben jetzt 4 Dateinamen in jeder Datei, all_files-*

Wählen Sie eine aus, sagen Sie all_files-aaund machen Sie Ihre Kopie:

xargs -I{} cp {} folder_for_batch_1 < all_files-aa


Wenn das Ziel nur darin besteht, sie zu stapeln, gibt es einen VIEL einfacheren Weg! ls | xargs -iX -n20 cp X target_folder/würde cp auf Dateien in Stapeln von 20 ausführen, bis sie alle fertig waren.
Caleb

Der Unterschied besteht darin, dass Ihre Version und Ihr Zielordner für alle Stapel gleich sind.
Kann Burak Çilingir
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.