Umbenennen von Dateien mit ihrem Pfadnamen

8

Ich habe eine .bdf-Datei in Unterordnern. Alle .bdf haben den gleichen Namen: Loads.bdf

Beispiel:

/home/user/folderxx/folderxxx/Load.bdf
/home/user/folderxx/folderxxx/Load.bdf

Ich muss alle Load.bdf-Dateien finden (und in einen neuen Ordner kopieren) und sie mit ihrem Pfadnamen umbenennen.

Beispiel: Nach der beabsichtigten Operation sollte so etwas angezeigt werden.

folder001_folderAAA_Load.bdf
folder002_folderBBB_Load.bdf
sh999
quelle

Antworten:

11

Ich würde das mcpTool aus dem mmvPaket ("multiple move") dafür verwenden:

mcp '/home/user/*/*/Load.bdf' '#1_#2_Load.bdf'

Der #1, #2usw. in dem zweiten String wird durch den Inhalt des entsprechenden 1., 2. usw. Wildcard von der ersten Zeichenfolge ersetzt werden. Beachten Sie, dass der Pfad in einfachen Anführungszeichen steht, sodass die Platzhalter von mcpund nicht von der Shell interpretiert werden .

Mit dem angezeigten Befehl werden die Dateien in das aktuelle Verzeichnis kopiert. Wenn Sie ersetzen mcpmit mmv, werden die Dateien stattdessen verschoben werden.

Dubu
quelle
Strings mit doppelten Anführungszeichen haben auch keine Platzhaltererweiterung, zumindest in Bash.
Daniel Beck
Dies war nützlich für mich, um den Namen des Ordners in jede Datei zu kopierenmmv '*/*.m4a' '#1.m4a'
ajr-dev
5

Mit prename( renameauf vielen Systemen alias ) ist dies ohne mehrere Läufe von mvoder möglich cp:

cd /home/user
find . -type f -name 'Loads.bdf' -exec \
  prename -n 's:^./::; s:/:_:g; s:^:destination/:' {} +

Entfernen Sie das, -nwenn Sie sicher sind, dass dadurch die gewünschten Dateien verschoben werden.

Aktualisieren

Um die Dateien zu kopieren, anstatt sie zu verschieben, kopieren Sie am schnellsten zuerst mit cpiooder paxund benennen sie dann wie zuvor um. ZB (mit GNU cpio):

cd /home/user
find . -type f -name 'Loads.bdf | cpio -p --make-directories destination

cd destination
find . -type f -name 'Loads.bdf' -exec  prename -n 's:^./::; s:/:_:g' {} +

Beachten Sie, dass paxPOSIX und LSB cpiozwar nicht mehr POSIX sind, cpioaber immer noch das Programm ist, das häufig auf vielen Systemen verwendet wird.

Um Dateinamen mit Zeilenumbrüchen mit GNU find/ zu behandeln cpio, ist es möglich, -print0zu findund -0zu hinzuzufügen cpio.

Update 2

Die paxLösung ist ein Einzeiler (ohne den cd):

cd /home/user
find . -name 'Loads.bdf' | cut -d/ -f 2- | pax -rws ':/:_:g' destination

Oder für einen beliebigen Dateinamen (und GNU find):

find /home/user -name 'Loads.bdf' -printf '%P\0' | pax -0rws ':/:_:g' destination
Graeme
quelle
Es gibt zwei Umbenennungen , die Perl- Umbenennung (auch bekannt als prename, aber renamein Ubuntu standardmäßig aufgerufen ) und die andere , die keinen regulären Ausdruck verwendet (bekannt als renameArch und Red Hat). Auch -execdirist bevorzugt -exec(siehe man find). Verschiebt dieser Befehl die Dateien nicht und kopiert sie nicht?
Sparhawk
@ Parhawk, ja deshalb habe ich angegeben prename. Obwohl ich den 'Kopie'-Teil in der Frage verpasst habe.
Graeme
Ah okay (war das eine Bearbeitung?). Vielleicht habe ich es einfach falsch gelesen.
Sparhawk
@ Parhawk, keine Bearbeitung. Guter Anruf für unterwegs gegen Kopie, obwohl ich jetzt eine aktualisierte Lösung hinzugefügt habe.
Graeme
1
@Tim, mit der paxLösung aktualisiert , verfügt über eine eigene Such- / Ersetzungsoption.
Graeme
3

Wenn Sie dies auf einem System tun müssen, auf dem die in einigen anderen Antworten genannten Tools nicht vorhanden sind (z. B. mcp und mmv oder Vorname), und Sie dies vollständig in der Shell tun möchten, können Sie etwas tun mögen:

#!/usr/bin/env bash

oldpath="/home/user"
newpath="/home/user/newfolder"

for file in $(find $oldpath -type f -name Load.bdf); do
        shortname=${file#$oldpath/}
        newname="$newpath/${shortname//\//_}"
        if [ -f $newname ]; then
                echo "$newname already exists."
        else
                echo "copy: $file"
                echo "  --> $newname"
                cp $file $newname
        fi
done

Dieses Skript findet alle Load.bdfim oldpathVerzeichnis genannten Dateien , mischt die Verzeichnisnamen in einen neuen Dateinamen und kopiert sie in Ihr Zielverzeichnis. Wir können auch prüfen, ob bereits kopierte Dateien vorhanden sind, falls Sie diese mehrmals ausführen müssen, und wir müssen nicht alle Dateien erneut kopieren.

Die resultierende Verzeichnisstruktur würde am Ende folgendermaßen aussehen:

bash$ find . -type f
/home/user/folder001/folderAAA/Load.bdf
/home/user/folder002/folderBBB/Load.bdf
/home/user/folder003/folderCCC/Load.bdf
/home/user/newfolder/folder001_folderAAA_Load.bdf
/home/user/newfolder/folder002_folderBBB_Load.bdf
/home/user/newfolder/folder003_folderCCC_Load.bdf
Tim Kennedy
quelle
Vielen Dank für Ihre Informationen. Ich habe viel mehr Informationen als ich brauche. Danke nochmal.
Sh999
1
Genial .. Sie könnten auch die gesamte Logik der Dateiexistenz an cp noclobber auslagern, indem Sie das gesamte if / else löschen und cp -n $ file $ newname
KeiferJ
1

In zsh ist es einfach mit zmv.

autoload -U zmv
cd /home/user
zmv '*/*/*' '${1//\//_}'
Gilles 'SO - hör auf böse zu sein'
quelle
0
env - sh <<\SCRIPT

    t=/home/user/target f=folder
    cd "${t%/*}" && mkdir -p "$t"
    set -- $f??/$f???/Load.BDF
    while [ -e "$1" ] ; do
        cp "$1" "$t/$(IFS=/
            printf '%s_%s_%s\n' $1)"
    shift ; done

SCRIPT

Ich denke, das ist alles ein vollständig portables Shell-Skript - und es ist ziemlich einfach gemacht, obwohl ich zuerst meine Zweifel hatte.

mikeserv
quelle