Comment trouver un fichier et le déplacer dans le répertoire dans lequel il a été trouvé


3

J'essaie de renommer des fichiers dans des sous-répertoires à l'aide xargsde la commande suivante:

find . -name oldfile.txt -print0 | xargs -n 1 -0 -I % mv % newfile.txt

Le problème est que le fichier est déplacé dans le répertoire dans lequel j’exécute la commande au lieu du répertoire dans lequel il oldfile.txtse trouve. Je ne peux pas sembler être la solution à ce problème, des idées?

Je pense que je peux peut-être obtenir le répertoire à partir du chemin du fichier trouvé, puis l'ajouter à l'avant du deuxième paramètre de, mvmais comment cela fonctionnerait-il?

Réponses:


3

Au lieu de faire appel à des commandes externes, où vous perdez les informations sur le répertoire en cours, vous pouvez utiliser findl’ -execdiroption permettant à ce dernier d’exécuter des commandes dans le répertoire dans lequel un fichier a été trouvé.

find . -name oldfile.txt -execdir mv -- {} newfile.txt \;

C’est en fait une version plus sécurisée -execqui est préférée dans la plupart des situations. Le seul inconvénient est que ce n'est pas spécifié par POSIX, donc vous ne le trouverez pas dans toutes les findvariantes - mais au moins dans GNU findet BSD, findvous le pouvez.

Si vous voulez être plus sûr, vous devriez appeler mvcomme mv -- source targetsi un fichier commençant par un tiret n'était pas interprété incorrectement comme un argument mv.


Si, pour une raison quelconque, vous ne souhaitez pas utiliser -execdirou avoir d'autres tâches compliquées, ou si vous souhaitez simplement en apprendre un peu plus sur Bash, voici comment obtenir le dossier et déplacer le fichier en fonction de cela:

find . -name oldfile.txt -exec bash -c 'mv -- "${0}" "$(dirname $0)"/newfile.txt' {} \;

Ici, {}passe le chemin complet à bashas $0. Nous obtenons son nom de répertoire via commande substitution ( $(…)), puis ajoutons le nouveau nom. L'argument d'origine et le nom du répertoire doivent être cités deux fois pour empêcher les espaces de rompre la commande - sinon, mvon penserait que vous essayez de déplacer deux fichiers appelés fooet barlorsque le fichier est réellement appelé foo bar, par exemple.


Cela a fonctionné! Excellente solution. Le troisième paramètre de mvest le répertoire? Je n'ai jamais vu mv avoir un troisième param. J'ai regardé le manuel mais cela ne semble pas clair.
Chris Bier

Non, ça n'a rien à voir avec mv. Le \;fait partie de la -exec/ l' -execdiroption - voir le findmanuel , je vous lié. Vous devez toujours l’inclure pour que findla fin de la commande spécifiée soit reconnue exec.
Slhck

Ah, je vois! Both of these constructions need to be escaped (with a ‘\’) or quoted to protect them from expansion by the shell.Cela signifie que cela {}devrait également être évité.
Chris Bier

Vous n'avez pas vraiment besoin de vous échapper ou de citer {}, cela fonctionne également sans cela dans la plupart des interprétations find. Citer {}n'est nécessaire que s'il est interprété autrement par le shell, ce qui n'est généralement pas le cas. Je pense que @DanielBeck a récemment eu un problème avec le fishshell et cela - mais je ne suis pas tout à fait sûr que ce fishsoit la cause du problème.
Slhck

Ajout d'un autre exemple sur la manière d'obtenir ce dont vous avez besoin, bien qu'un peu plus compliqué que nécessaire.
Slhck
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.