2009-02-13 6 views
161

Also, wenn ich in meinem Home-Verzeichnis bin und foo.c nach ~/bar/baz/foo.c verschieben möchte, aber diese Verzeichnisse nicht existieren, gibt es eine Möglichkeit, diese Verzeichnisse automatisch zu erstellen, so dass Sie nurGibt es eine Möglichkeit, mv das Verzeichnis zu erstellen, in das verschoben werden soll, wenn es nicht existiert?

mv foo.c ~/bar/baz/ 

eingeben müssten und alles würde funktionieren? Es scheint so, als könntest du mv zu einem einfachen Bash-Skript hinzufügen, das prüfen würde, ob diese Verzeichnisse existieren und wenn nicht, würden wir mkdir und dann mv aufrufen, aber ich dachte, ich würde nachsehen, ob jemand eine bessere Idee hat.

Antwort

9

können Sie verwenden mkdir:

mkdir -p ~/bar/baz/ && \ 
mv foo.c ~/bar/baz/ 

Ein einfaches Skript automatisch zu tun (nicht getestet):

#!/bin/sh 

# Grab the last argument (argument number $#)  
eval LAST_ARG=\$$# 

# Strip the filename (if it exists) from the destination, getting the directory 
DIR_NAME=`echo $2 | sed -e 's_/[^/]*$__'` 

# Move to the directory, making the directory if necessary 
mkdir -p "$DIR_NAME" || exit 
mv "[email protected]" 
+0

Wenn ich "$ dirname ~? Bar/baz /" starte, bekomme ich "/ home/dmckee/bar", was Sie nicht wollen ... – dmckee

+0

@dmckee, Ah, Sie haben Recht. Irgendeine Idee, wie man das löst? Wenn Sie ~/bar/baz eingeben, wollen Sie entweder (~) nach ~/bar/kopieren und in baz umbenennen, oder (b) nach ~/bar/baz/kopieren. Was ist das bessere Werkzeug für den Job? – strager

+0

Sie könnten "[-d" $ 2 "] verwenden, um es zu sortieren, aber das ist nicht so schön ... – dmckee

5

Das Skript folgende Shell, vielleicht?

#!/bin/sh 
if [[ -e $1 ]] 
then 
    if [[ ! -d $2 ]] 
    then 
    mkdir --parents $2 
    fi 
fi 
mv $1 $2 

Das ist der grundlegende Teil. Vielleicht möchten Sie etwas hinzufügen, um nach Argumenten zu suchen, und Sie möchten vielleicht, dass sich das Verhalten ändert, wenn das Ziel existiert oder das Quellverzeichnis existiert oder nicht existiert (dh überschreiben Sie nichts, das nicht existiert) .

+1

Mit Ihrem Code wird die Verschiebung nicht ausgeführt, wenn das Verzeichnis nicht existiert! – strager

+1

Und Sie haben die "-p" -Flagge zu mkdir verpasst. – dmckee

+0

Wenn ein Verzeichnis nicht existiert, warum erstellen Sie es, wenn Sie es einfach verschieben wollen? (-p flag fixed) –

183

Wie dieser Einzeiler (in bash):

mkdir --parents ./some/path/; mv yourfile.txt $_ 

brechen, dass nach unten:

mkdir --parents ./some/path 

das Verzeichnis (einschließlich aller Zwischenverzeichnisse) erstellt, wonach:

mv yourfile.txt $_ 

verschiebt die Datei in dieses Verzeichnis ($ _ expandiert zum letzten an die vorherige Shell übergebenen Argument c ommand, dh: das neu erstellte Verzeichnis).

Ich bin nicht sicher, wie weit das in anderen Shells funktioniert, aber es könnte Ihnen einige Ideen geben, wonach Sie suchen sollten. Hier

ist ein Beispiel dieser Technik:

$ > ls 
$ > touch yourfile.txt 
$ > ls 
yourfile.txt 
$ > mkdir --parents ./some/path/; mv yourfile.txt $_ 
$ > ls -F 
some/ 
$ > ls some/path/ 
yourfile.txt 
+17

Schön mit dem '$ _'. – dmckee

+0

Einverstanden, aber dies ist eine weniger allgemeine Lösung. Meine Lösung könnte als mv-Substitution (also als Alias ​​in bash) dienen (vorausgesetzt, es funktioniert einwandfrei - noch ungetestet!). – strager

+1

Warum die Besessenheit mit redundanten '. /' Überall? Die Argumente sind keine Befehle in PATH ohne das '.' -Verzeichnis ... – Jens

1

Sie selbst Klammer-Erweiterungen verwenden können:

mkdir -p directory{1..3}/subdirectory{1..3}/subsubdirectory{1..2}  
  • die drei Verzeichnisse erstellt (directory1, directory2, directory3),
    • und in jedem von ihnen zwei Unterverzeichnisse (Unterverzeichnis1, Unterverzeichnis2),
      • und in jedem von ihnen zwei subsubdirectories (subsubdirectory1 und subsubdirectory2).

Sie haben bash 3.0 oder höher zu verwenden.

+3

Interessant, beantwortet aber die Frage des OP nicht. –

16

Speichern Sie als Skript namens mv oder mv.sh

#!/bin/bash 
# mv.sh 
dir="$2" 
tmp="$2"; tmp="${tmp: -1}" 
[ "$tmp" != "/" ] && dir="$(dirname "$2")" 
[ -a "$dir" ] || 
mkdir -p "$dir" && 
mv "[email protected]" 

oder am Ende Ihrer Datei ~/.bashrc als Funktion setzen, die den Standard mv auf jeden neuen Terminal ersetzt. Die Verwendung einer Funktion erlaubt bash, den Speicher zu behalten, anstatt jedes Mal eine Skriptdatei lesen zu müssen.

function mv() 
{ 
    dir="$2" 
    tmp="$2"; tmp="${tmp: -1}" 
    [ "$tmp" != "/" ] && dir="$(dirname "$2")" 
    [ -a "$dir" ] || 
    mkdir -p "$dir" && 
    mv "[email protected]" 
} 

Diese basieren auf der Vorlage von Chris Lutz.

+1

Dies beantwortet die Frage am ehesten IMHO. Der Benutzer möchte einen erweiterten 'mv'-Befehl. Besonders nützlich für das Scripting, dh Sie möchten die Checks nicht unbedingt ausführen und 'mkdir -p' jederzeit ausführen, wenn Sie' mv' benötigen. Aber da ich das Standardfehlerverhalten für 'mv' haben möchte, habe ich den Funktionsnamen in' mvp' geändert - damit ich weiß, wann ich Verzeichnisse erstellen kann. –

+0

Scheint wie die beste Lösungsidee, aber die Implementierung stürzt viel ab. –

+1

@UlisesLayera Ich habe den Algorithmus modifiziert, um ihn robuster zu machen. Es sollte jetzt nicht abstürzen – Sepero

38
mkdir -p `dirname /destination/moved_file_name.txt` 
mv /full/path/the/file.txt /destination/moved_file_name.txt 
+11

+1 für das Schreiben einer Textwand für triviale Dinge. Ich hätte mit einem "Nein" angefangen :) – OlivierBlanvillain

+0

Das ist großartig! Beste Antwort!Danke – radtek

+1

Ich bin der einzige, der realisiert, dass dieser Code keinen Sinn macht? Sie erstellen rekursiv den absoluten Pfad zur vorhandenen Datei (was bedeutet, dass dieser Pfad bereits existiert) und verschieben Sie die Datei dann an einen Ort (der in Ihrem Beispiel nicht existiert). – user544262772

2

dümmer, aber Arbeitsweise:

mkdir -p $2 
rmdir $2 
mv $1 $2 

das Verzeichnis mit mkdir -p Machen Sie ein temporäres Verzeichnis enthält, die Aktien der Zieldateiname ist, entfernen Sie dann die Dateinamen-Verzeichnis mit einem einfachen rmdir, dann verschieben Sie Ihre Datei an ihr neues Ziel. Ich denke, Antwort mit dirname ist wahrscheinlich die beste aber.

2

Es klingt wie die Antwort nein :). Ich möchte nicht wirklich einen Alias ​​oder eine Funktion erstellen, nur um das zu tun, oft weil es einmalig ist und ich bin gerade mitten in der Eingabe des Befehls mv, aber ich fand etwas, das gut dafür funktioniert:

mv *.sh shell_files/also_with_subdir/ || mkdir -p $_ 

Wenn mv fehlschlägt (dir nicht existiert), wird es das Verzeichnis (das ist das letzte Argument zum vorherigen Befehl, also $_ hat es). Also einfach diesen Befehl ausführen, dann bis, um es erneut auszuführen, und diesmal sollte mv erfolgreich sein.

0
$what=/path/to/file; 
$dest=/dest/path; 

mkdir -p "$(dirname "$dest")"; 
mv "$what" "$dest" 
+1

um es zu einem eigenständigen SH-Skript zu machen, ersetzen Sie einfach $ dest und $ src durch $ 1 und $ 2 – cab404

2

Der einfachste Weg, dies zu tun ist:

mkdir [directorie name] && mv [filename] $_

Nehmen wir an, ich pdf-Dateien heruntergeladen in meinem Download directorie gelegen (~/Download), und ich möchte alle dann in einem directorie bewegen, die ‚doesn t Ausgang (sagen wir "my_PDF").
Ich werde die folgende commande (sicherstellen, dass meine aktuelle Arbeits directorie ist ~/download) Typ:

mkdir my_PDF && mv *.pdf $_

Sie Option -p hinzufügen können, um mkdir wenn Sie Verzeichnisse wie dies nur erstellen möchten: (soll ich ein subdirectorie namens erstellen möchten "python"):
mkdir -p my_PDF/python && mv *.pdf $_

1

Meine eine Saite Lösung:

test -d "/home/newdir/" || mkdir -p "/home/newdir/" && mv /home/test.txt /home/newdir/ 
Verwandte Themen