ubuntuusers.de

Dateien mit Anfangsbuchstaben c-z kopieren

Status: Gelöst | Ubuntu-Version: Ubuntu 18.04 (Bionic Beaver)
Antworten |

Wolfmann

Anmeldungsdatum:
7. Oktober 2018

Beiträge: 352

Hallo,

Ich hoffe, dass ich mit meiner Frage hier richtig bin. Ansonsten bitte in den richtigen Bereich verschieben.

Und zwar möchte ich gerne aus einem Ordner einen Teil der Dateien auf eine andere Festplatte kopieren (alle Dateien die mit einem Buchstaben ab c beginnen).

Ich habe mir dazu erstmal eine Variable erstellt:

1
VAR= ls /Pfad/zum/ordner | grep ^'[c-zC-Z]'

Soweit so gut. Aber wie kriege ich die Bash jetzt dazu, den Inhalt der Variable abzugleichen und diese Dateien dann zu kopieren. Müsste ich dazu eventuell auch nach den Dateiendungen (z.B. txt) einen Zeilenumbruch einleiten, damit das nicht direkt hintereinander steht?

Für Antworten danke ich.

Moderiert von sebix:

Thema in einen passenden Forenbereich verschoben. Bitte beachte die als wichtig markierten Themen („Welche Themen gehören hier her und welche nicht?“) in jedem Forenbereich. Danke.

dingsbums

Anmeldungsdatum:
13. November 2010

Beiträge: 3791

find "/pfad/zur/quelle" -mindepth 1 -maxdepth 1 -type f -iname "[c-z]*" -exec cp -pv "{}" "/pfad/zum/ziel" \;

Wolfmann

(Themenstarter)

Anmeldungsdatum:
7. Oktober 2018

Beiträge: 352

Danke dir. So gehts auch ☺

Interessehalber gefragt: Würde mein ursprünglicher Lösungsansatz mit der Variablen auch irgendwie funktionieren?

dingsbums

Anmeldungsdatum:
13. November 2010

Beiträge: 3791

Vermutlich eher nicht, da du in deiner Variable alle Dateinamen in einem String zurückbekommst. Ich wüsste nicht, wie du das dann wieder auflösen kannst.

Unter bestimmten Voraussetzungen (keine Unterverzeichnisse im Quellpfad und keine Leerzeichen in den Dateinamen) würde Folgendes auch funktionieren:

1
2
3
for datei in $(ls /pfad/zur/quelle | grep ^'[c-zC-Z]');do
   cp -vp $datei /pfad/zum/ziel
done

Die find-Variante berücksichtigt auch keine Dateien in Unterverzeichnissen.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13219

dingsbums schrieb:

1
2
3
for datei in $(ls /pfad/zur/quelle | grep ^'[c-zC-Z]');do
   cp -vp $datei /pfad/zum/ziel
done

Ganz schlechte Idee die Ausgabe von ls zu parsen. Das ist total fehleranfällig und auch völlig überflüssig (s. Link auf meiner Profilseite).

dingsbums schrieb:

find "/pfad/zur/quelle" -mindepth 1 -maxdepth 1 -type f -iname "[c-z]*" -exec cp -pv "{}" "/pfad/zum/ziel" \;

Das ist viel zu umständlich. Es reicht völlig:

1
cp -t ziel [c-Z]*

Wenn nocaseglob an ist, geht auch

1
cp -t ziel [c-z]*

haveaproblem

Anmeldungsdatum:
2. Januar 2015

Beiträge: 1163

Wolfmann schrieb:

Interessehalber gefragt: Würde mein ursprünglicher Lösungsansatz mit der Variablen auch irgendwie funktionieren?

Tja, da ich irgendwie vor dem Schlafen gehen noch hier drauf gestoßen bin, habe ich es mir zur Herausforderung gemacht das zu probieren (auch um mal ein bisschen mit der Bash zu üben).

1
2
3
4
5
6
7
8
9
VAR=$(ls $HOME | grep ^'[c-zC-Z]')
numline=$( echo "${VAR}" | wc -l | tail -1)
i=1
while [ $i -le $numline ]
do
mvedfile=$(echo "${VAR}" | sed -n ${i}p)
echo Datei\ $mvedfile\ sollte\ jetzt\ gemovet\ werden
 i=$(( $i + 1 ))
done

Das letzte echo dann durch einen mv Befehl ersetzen. Aber wie andere schon erwähnten ls zu parsen ist Fehleranfällig und es gibt hier deutlich bessere Lösungen.

PS: Du hast übrigens schon den ersten Fehler bei deiner Variablen Setzung gemacht, schau mal was

VAR= ls /Pfad/zum/ordner | grep ^'[c-zC-Z]'; echo $VAR

ausgibt 😉. Richtig wäre es so:

VAR=$(ls $HOME | grep ^'[c-zC-Z]')

mit einem echo dahinter, kannst du dann auch den Variablen inhalt betrachten.

Dann noch allen Mitlesern eine gute Nacht, oder vlt. auch schon einen guten Morgen.

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11269

Wohnort: München

haveaproblem schrieb:

Wolfmann schrieb:

Interessehalber gefragt: Würde mein ursprünglicher Lösungsansatz mit der Variablen auch irgendwie funktionieren?

Tja, da ich irgendwie vor dem Schlafen gehen noch hier drauf gestoßen bin, habe ich es mir zur Herausforderung gemacht das zu probieren (auch um mal ein bisschen mit der Bash zu üben).

Das kann man mit Arrays in der Bash einfacher haben:

1
2
3
4
5
6
#!/bin/bash
files_to_move=(/pfad/zur/quelle/[c-zC-Z]*)
for file in "${files_to_move[@]}"
do
    echo "do something with $file ..."
done

Wolfmann

(Themenstarter)

Anmeldungsdatum:
7. Oktober 2018

Beiträge: 352

Vielen Dank an alle, die hier gepostet haben.

Ich weiß schon, dass das mit der Variablen nicht am fehlerunfälligsten oder effektivsten ist. Aber mir gings hier auch um den Übungs- und Lerneffekt.

Nochmals danke und einen schönen Sonntag!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13219

Ich hätte noch erwähnen sollen, dass ich davon ausgegangen bin, dass es keine Verzeichnisse in dem Quellverzeichnis gibt. Sollte das doch der Fall sein, gibt es ein paar Fehlermeldungen, die man allerdings ignorieren oder durch Umleitung nach /dev/null verbergen kann. Oder man arbeitet selektiver

1
find quelle -maxdepth 1 -type f -iname '[c-z]*' -exec cp -t ziel {} +

oder

1
2
3
for f in quelle/[c-Z]*; do
  [ -f "$f" ] && cp -t ziel "$f"
done

Wolfmann schrieb:

Interessehalber gefragt: Würde mein ursprünglicher Lösungsansatz mit der Variablen auch irgendwie funktionieren?

Die Zwischenspeicherung in einer Variable - ob Array oder anders - ist i.d.R. nur sinnvoll, wenn man die Daten mehrfach verarbeiten will. Im aktuellen Beispiel scheint mir das eher nicht so zu sein. Im Gegenteil erzeugen Lösungen mit Variable u.U. neue Probleme, wie man sieht. Da ist es einfacher, die Liste der Namen zu globben und dann direkt in einer Schleife zu verarbeiten. Das hat außerdem den Vorteil, dass man keine bash für die Arrays braucht - meine Lösungen funktionieren auch in der sh.

Man muss allerdings aufpassen, weil die sh und die bash etwas anders mit Groß- und Kleinschreibung umgehen. Für die sh müsste es so aussehen:

1
2
3
for f in quelle/[c-zC-Z]*; do
  [ -f "$f" ] && cp -t ziel "$f"
done

(Details findet man in der bash-Doku, wenn man nach "LC_COLLATE" sucht.)

Antworten |