Bash - Déplace de manière récursive tous les fichiers des dossiers portant le même nom dans leur répertoire parent

0

J'ai une bibliothèque de documents où tous mes fichiers se trouvent dans des dossiers basés sur le nom de la catégorie, mais ils se trouvent également dans des sous-dossiers appelés "pdf". Existe-t-il un moyen dans bash de parcourir tous les répertoires de la bibliothèque et de déplacer tous les fichiers des dossiers nommés pdf dans leur répertoire parent?

PortlandRyan
la source

Réponses:

2

Ce qui suit déplace chaque fichier d’un pdfdossier vers le répertoire parent.

find ~/some/folder -type d -name 'pdf' -print0 | while IFS= read -d '' dir
do
  find "$dir" -type f -maxdepth 1 -exec echo mv -- {} "$dir"/.. \;
done

Supprimez-le echoune fois que vous êtes certain qu'il répond à vos besoins.

Notez que cela écrasera les fichiers sans demander quand le parent en contient déjà un du même nom. Utilisez-le mv -ipour qu'il vous invite à confirmer avant d'écraser quoi que ce soit.

slhck
la source
De rien. Depuis que vous avez demandé des tutoriels sur Bash: Il existe des problèmes courants , ainsi que des pièges , à la fois sur le wiki de Bash de Greg - une très bonne ressource. Consultez également le Wiki Bash Hackers et le Guide de script avancé Bash
slhck
1

Voici ce à quoi je pensais. Ce n'est pas la plus jolie chose, mais cela fonctionne selon vos spécifications:

find . -ipath "*pdf/*.pdf" -type f -print0 | xargs -0 -I{} sh -c 'mv "{}" "$(dirname "{}")"/..'

Il déplace uniquement les .pdffichiers des sous- pdfdossiers dans les répertoires parent correspondants. Pour modifier la commande afin de déplacer tous les fichiers des sous- pdfdossiers, ajustez l' ipathargument en *pdf/*.


Exemple d'utilisation

$ find .
.
./category1
./category1/other_dir
./category1/other_dir/c1o1.txt
./category1/pdf
./category1/pdf/c1p1.pdf
./category1/pdf/c1p2.pdf
./category1/pdf/c1p3.pdf
./category2
./category2/other_dir
./category2/other_dir/c2o1.txt
./category2/pdf
./category2/pdf/c2p1.pdf
./category2/pdf/c2p2.pdf
./category2/pdf/c2p3.pdf

$ find . -ipath "*pdf/*.pdf" -type f -print0 | xargs -0 -I{} sh -c 'mv "{}" "$(dirname "{}")"/..'
.
./category1
./category1/c1p1.pdf
./category1/c1p2.pdf
./category1/c1p3.pdf
./category1/other_dir
./category1/other_dir/c1o1.txt
./category1/pdf
./category2
./category2/c2p1.pdf
./category2/c2p2.pdf
./category2/c2p3.pdf
./category2/other_dir
./category2/other_dir/c2o1.txt
./category2/pdf
Pluie
la source
2
Pour la tuyauterie de findà xargs, vous devriez utiliser find … -print0 | xargs -0 ….
Slhck
@slhck Vous avez raison; Merci d'avoir fait remarquer cela. Je viens de mettre à jour ma réponse.
Rain
Belle avec le ipath, je n'ai pas pensé à ça. $(dirname $(dirname {}))peut être abrégé "$(dirname {})"/..si je ne me trompe pas. (En général, les arguments {}devraient être cités pour empêcher les fichiers comportant des espaces dans leur nom ou similaires de s'afficher sous forme d'arguments multiples mv.)
slhck
Oui, je viens de le tester. ça fonctionne bien. "$(dirname {})"/..le rend beaucoup plus propre, aussi. Je n'ai même pas pensé à le citer, non plus. Tout chemin avec des espaces briserait la commande d'origine.
Pluie
Vous pensez DOS. Sous Unix (et al.), *.*Récupère (uniquement) tous les fichiers dont le nom contient un point . Pour obtenir tous les fichiers, utilisez tout simplement *(et même cela pourrait ne pas avoir les fichiers dont le nom commence par un point).
Scott