web-dev-qa-db-fra.com

Existe-t-il un moyen de faire en sorte que mv crée le répertoire vers lequel il doit être déplacé s'il n'existe pas?

Donc, si je suis dans mon répertoire personnel et que je veux déplacer foo.c dans ~/bar/baz/foo.c, mais que ces répertoires n'existent pas, existe-t-il un moyen de les créer automatiquement, de sorte que il vous suffirait de taper

mv foo.c ~/bar/baz/ 

et tout irait bien? On dirait que vous pouvez utiliser alias mv avec un simple script bash qui vérifierait si ces répertoires existaient et, sinon, appellerait mkdir puis mv, mais je pensais que je vérifierais si quelqu'un avait une meilleure idée.

202
Paul Wicks

Que diriez-vous de cette ligne (en bash):

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

Décomposer cela:

mkdir --parents ./some/path

crée le répertoire (y compris tous les répertoires intermédiaires), après quoi:

mv yourfile.txt $_

déplace le fichier dans ce répertoire ($ _ s’agrandit avec le dernier argument transmis à la commande Shell précédente, c’est-à-dire: le répertoire nouvellement créé).

Je ne sais pas dans quelle mesure cela fonctionnera dans d'autres coquilles, mais cela pourrait vous donner quelques idées sur ce qu'il faut rechercher.

Voici un exemple utilisant cette technique:

$ > ls
$ > touch yourfile.txt
$ > ls
yourfile.txt
$ > mkdir --parents ./some/path/; mv yourfile.txt $_
$ > ls -F
some/
$ > ls some/path/
yourfile.txt
221
KarstenF
mkdir -p `dirname /destination/moved_file_name.txt`  
mv /full/path/the/file.txt  /destination/moved_file_name.txt
53
Billmc

Enregistrer en tant que script nommé mv ou mv.sh

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

Ou mettez à la fin de votre fichier ~/.bashrc une fonction qui remplace le mv par défaut sur chaque nouveau terminal. L'utilisation d'une fonction permet à bash de conserver sa mémoire, au lieu d'avoir à lire un fichier de script à chaque fois.

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

Ces basé sur la soumission de Chris Lutz.

20
Sepero

Vous pouvez utiliser mkdir:

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

Un script simple pour le faire automatiquement (non testé):

#!/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 "$@"
13
strager

Le script shell suivant, peut-être?

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

C'est la partie de base. Vous voudrez peut-être ajouter un peu pour vérifier les arguments, et vous voudrez peut-être que le comportement change si la destination existe, ou le répertoire source existe ou n'existe pas (c.-à-d. Ne remplacez pas quelque chose qui n'existe pas) .

5
Chris Lutz

On dirait que la réponse est non :). Je ne veux pas vraiment créer un alias ou une fonction juste pour le faire, souvent parce que c'est unique et que je suis déjà en train de taper la commande mvname__, mais j'ai trouvé quelque chose qui fonctionne bien pour cela:

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

Si mvéchoue (le répertoire n'existe pas), le répertoire sera créé (le dernier argument de la commande précédente, donc $_ l'a). Alors, lancez cette commande, puis up pour l'exécuter à nouveau et cette fois mvdevrait réussir.

4
Pat

Sillier, mais façon travaillante:

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

Créez le répertoire avec mkdir -p, y compris un répertoire temporaire qui partage le nom du fichier de destination, puis supprimez ce répertoire avec un simple rmdir, puis déplacez votre fichier vers sa nouvelle destination . Je pense que répondre à l'aide de dirname est probablement le mieux cependant.

2
Blarn Blarnson

La façon la plus simple de le faire est:

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

Supposons que j’ai téléchargé des fichiers pdf situés dans mon répertoire de téléchargement (~/download) et que je souhaite ensuite tous les déplacer dans un répertoire qui ne se ferme pas (disons "mon_PDF").
Je vais taper la commande suivante (en vérifiant que mon répertoire de travail actuel est ~/download):

mkdir my_PDF && mv *.pdf $_

Vous pouvez ajouter l'option -p à mkdir si vous souhaitez créer des sous-répertoires similaires à ceux-ci: (supposons que je souhaite créer un sous-répertoire nommé "python"):
mkdir -p my_PDF/python && mv *.pdf $_

2
Abdoul Seibou

Vous pouvez même utiliser des extensions d'accolade:

mkdir -p directory{1..3}/subdirectory{1..3}/subsubdirectory{1..2}      
  • qui crée 3 répertoires (répertoire1, répertoire2, répertoire3),
    • et dans chacun d’eux deux sous-répertoires (sous-répertoire1, sous-répertoire2),
      • et dans chacun d'eux deux sous-répertoires (subsubdirectory1 et subsubdirectory2).

Vous devez utiliser bash 3.0 ou plus récent.

1
Stefan Gruenwald

rsync command peut faire l'affaire seulement si le dernier répertoire du chemin de destination n'existe pas, par exemple. pour le chemin de destination de ~/bar/baz/ si bar existe mais que baz n'existe pas, la commande suivante peut être utilisée:

rsync -av --remove-source-files foo.c ~/bar/baz/

-a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
-v, --verbose               increase verbosity
--remove-source-files   sender removes synchronized files (non-dir)

Dans ce cas, le répertoire baz sera créé s'il n'existe pas. Mais si bar et baz n'existent pas, rsync échouera:

sending incremental file list
rsync: mkdir "/root/bar/baz" failed: No such file or directory (2)
rsync error: error in file IO (code 11) at main.c(657) [Receiver=3.1.2]

Donc, fondamentalement, il devrait être prudent d'utiliser rsync -av --remove-source-files comme alias pour mv.

1
sepehr

Ma solution à une chaîne:

test -d "/home/newdir/" || mkdir -p "/home/newdir/" && mv /home/test.txt /home/newdir/
0
Andrey
$what=/path/to/file;
$dest=/dest/path;

mkdir -p "$(dirname "$dest")";
mv "$what" "$dest"
0
cab404

Code:

if [[ -e $1 && ! -e $2 ]]; then
   mkdir --parents --verbose -- "$(dirname -- "$2")"
fi
mv --verbose -- "$1" "$2"

Exemple:

arguments: "d1" "d2/sub"

mkdir: created directory 'd2'
renamed 'd1' -> 'd2/sub'
0
John Doe

Vous pouvez chaîner les commandes: mkdir ~/bar/baz | mv foo.c ~/bar/baz/
ou le script shell est ici:

#!/bin/bash
mkdir $2 | mv $1 $2

1. Ouvrir n'importe quel éditeur de texte
2. Copier-coller Script shell.
3. Enregistrer comme mkdir_mv.sh
4. Entrez le répertoire de votre script: cd your/script/directory
5. Changer le mode de fichier : chmod +x mkdir_mv.sh
6. Set alias: alias mv="./mkdir_mv.sh"
Maintenant, chaque fois que vous exécuterez la commande mv, le répertoire de déplacement sera créé s'il n'existe pas. 

0
Sharofiddin
((cd src-path && tar --remove-files -cf - files-to-move) | ( cd dst-path && tar -xf -))
0
svaardt