Déplacer chaque fichier qui n'est pas un répertoire

14

J'ai un répertoire que j'essaie de nettoyer qui contient à la fois des fichiers et des sous-répertoires. Ce que j'essaie de faire est simple: déplacer tous les fichiers dans un autre répertoire, mais laisser tous les sous-répertoires tels quels.

Je pense à quelque chose comme:

mv [*_but_no_dirs] ./other_directory

Il semble qu'il devrait y avoir un moyen simple de le faire avec des caractères génériques *et des expressions rationnelles ...

Quelqu'un a des idées?

Point d'interrogation
la source
1
Donc, déplacez tous les fichiers dans un sous-dossier, mais ignorez-en un dans les sous-répertoires?
Wilf
@Wilf: Exactement.
Questionmark
2
Dans zsh, vous pouvez le faire mv **/*(.) ./other_directory- avec bash, vous devrez cependant recourir à des commandes externes find.
godlygeek

Réponses:

12

Regex ne sont pas impliqués ici. Les caractères génériques dans bash (comme la plupart des autres shells) ne correspondent qu'aux fichiers en fonction des noms de fichier, et non en fonction du type de fichier ou d'autres caractéristiques. Il existe une façon de faire correspondre par type: l'ajout /à la fin du modèle ne fait correspondre que les répertoires ou les liens symboliques aux répertoires. De cette façon, vous pouvez déplacer des répertoires, puis déplacer ce qui reste, et déplacer des répertoires en arrière - lourd mais cela fonctionne.

tmp=$(TMPDIR=.. mktemp -d)
mv -- */ "$tmp"
mv -- * "$tmp"/other_directory/
mv "$tmp"/* .
rmdir "$tmp"

Un moyen standard de faire correspondre les fichiers par type est d'appeler find.

find . -name . -o -type d -prune -o -exec sh -c 'mv "$@" "$0"' other_directory/ {} +

Dans zsh, vous pouvez utiliser des qualificatifs glob pour faire correspondre les fichiers par type. Le .qualificatif correspond aux fichiers normaux; utiliser ^/pour faire correspondre tous les non-répertoires, ou -^/pour inclure également des liens symboliques vers les répertoires.

mv -- *(.) other_directory/

Dans n'importe quel shell, vous pouvez simplement boucler.

for x in *; do
   if ! [ -d "$x" ]; then
     mv -- "$x" other_directory/
   fi
done
Gilles 'SO- arrête d'être méchant'
la source
8

Vous pourriez utiliser quelque chose comme

find . -maxdepth 1 \( ! -type d \) -exec sh -c 'mv  "$@" MYDIR' _ {} \;

D'abord, nous utilisons findpour regarder uniquement dans le directoy actuel, puis nous ignorons les répertoires en utilisant ! -type d enfin nous exécutons shet déplaçons tout dans le répertoire de destination. Vous pourriez essayer {} +à la fin qui sera plus rapide.

Valentin Bajrami
la source
2
Un peu d'explication, s'il vous plaît ...
Questionmark
1
@Questionmark J'ai mis à jour la réponse et ajouté quelques explications. En outre, cela vaut la peine de visiter mywiki.wooledge.org/UsingFind
Valentin Bajrami
Pourquoi suggérez-vous -exec sh -c 'mv "$@" MYDIR' _ {} \;plutôt que -exec mv {} MYDIR \;? Juste pour obtenir quelque chose qui peut être rationalisé en changeant le \;en +? Vous pouvez le faire avec le -exec mv -t MYDIR {} +formulaire.
Scott
@Scott Je n'avais aucune idée du -tdrapeau. J'ai également expliqué dans la réponse que le +est plus rapide mais que toutes les findversions ne le prennent pas en charge. Le code ci-dessus est donc à peu près compatible avec n'importe quel findou shell utilisé.
Valentin Bajrami
1
@ val0x00ff: «… le code ci-dessus est à peu près compatible avec n'importe quel findshell utilisé.» Vrai, mais il en est ainsi find … -exec mv {} MYDIR \;, et qui utilise moins de ressources que … -exec sh -c 'mv "$@" MYDIR' _ {} \;.
Scott
0

C'est potentiellement un peu dangereux mais

cp * destination/
rm *

Comme cp et rm ne fonctionneront pas sur les répertoires sans le commutateur -r.

miick
la source
-1

Je suggérerais simplement de faire mv *.* destination/avec destination / être le dossier vers lequel vous vous déplacez.

Peter Z
la source
2
consultez: unix.stackexchange.com/help/formatting
Jeff Schaller
2
Les noms de répertoires peuvent contenir des «points» et les noms de fichiers peuvent les exclure (et le font souvent). Ainsi *.*, certains répertoires seront déplacés et certains fichiers resteront, ce qui n'est pas ce que le demandeur voulait.
dave_thompson_085
Désolé mais c'est complètement faux. Il déplacera simplement n'importe quoi avec un point dans son nom et ne bougera rien sans un. Les points ne sont en aucun cas exclusifs aux fichiers et ils ne sont pas non plus requis par les fichiers, donc cela ne fera que déplacer une sélection aléatoire de fichiers et de répertoires.
terdon
-2
mv $(ls -l | grep "^-" | awk '{print $9}') ./folder_where_move
sy s
la source