web-dev-qa-db-fra.com

Comment déplacez-vous tous les fichiers (y compris cachés) d'un répertoire à un autre?

Comment déplacer tous les fichiers d'un répertoire (y compris ceux cachés) vers un autre répertoire?

Par exemple, si j'ai un dossier "Foo" avec les fichiers ".hidden" et "notHidden" à l'intérieur, comment déplacer les deux fichiers dans un répertoire nommé "Bar"? Ce qui suit ne fonctionne pas, car le fichier ".hidden" reste dans "Foo".

mv Foo/* Bar/

Essayez-le vous-même.

mkdir Foo
mkdir Bar
touch Foo/.hidden
touch Foo/notHidden
mv Foo/* Bar/
155
Cory Klein

Zsh

mv Foo/*(DN) Bar/

ou

setopt -s glob_dots
mv Foo/*(N) Bar/

(Oubliez le (N) si vous savez que le répertoire n'est pas vide.)

Bash

shopt -s dotglob nullglob
mv Foo/* Bar/

Ksh93

Si vous savez que le répertoire n'est pas vide:

FIGNORE='.?(.)'
mv Foo/* Bar/

Standard (POSIX) sh

for x in Foo/* Foo/.[!.]* Foo/..?*; do
  if [ -e "$x" ]; then mv -- "$x" Bar/; fi
done

Si vous êtes prêt à laisser la commande mv retourner un état d'erreur même si elle a réussi, c'est beaucoup plus simple:

mv Foo/* Foo/.[!.]* Foo/..?* Bar/

GNU find et GNU mv

find Foo/ -mindepth 1 -maxdepth 1 -exec mv -t Bar/ -- {} +

Recherche standard

Si cela ne vous dérange pas de passer au répertoire source:

cd Foo/ &&
find . -name . -o -exec sh -c 'mv -- "$@" "$0"' ../Bar/ {} + -type d -Prune

Voici plus de détails sur le contrôle de la correspondance des fichiers dot dans bash, ksh93 et ​​zsh.

Bash

Définissez l'option dotglob .

$ echo *
none zero
$ shopt -s dotglob
$ echo *
..two .one none zero

Il y a aussi la variable GLOBIGNORE plus flexible , que vous pouvez définir sur une liste de motifs génériques séparés par deux-points à ignorer. S'il n'est pas défini (le paramètre par défaut), le shell se comporte comme si la valeur était vide si dotglob est définie, et comme si la valeur était .* si l'option est non définie. Voir Extension du nom de fichier dans le manuel. Les répertoires omniprésents . et .. sont toujours omis, sauf si le . correspond explicitement au modèle.

$ GLOBIGNORE='n*'
$ echo *
..two .one zero
$ echo .*
..two .one
$ unset GLOBIGNORE
$ echo .*
. .. ..two .one
$ GLOBIGNORE=.:..
$ echo .*
..two .one

Ksh93

Définissez la variable FIGNORE . S'il n'est pas défini (paramètre par défaut), le shell se comporte comme si la valeur était .*. Pour ignorer . et .., ils doivent être mis en correspondance explicitement (le manuel de ksh 93s + 2008-01-31 indique que . et .. sont toujours ignorés, mais cela ne décrit pas correctement le comportement réel).

$ echo *
none zero
$ FIGNORE='@(.|..)'
$ echo *
..two .one none zero
$ FIGNORE='n*'
$ echo *
. .. ..two .one zero

Vous pouvez inclure des fichiers de points dans un motif en les faisant correspondre explicitement.

$ unset FIGNORE
$ echo @(*|.[^.]*|..?*)
..two .one none zero

Pour que l'extension sorte vide si le répertoire est vide, utilisez l'option de correspondance de modèle N: ~(N)@(*|.[^.]*|..?*) ou ~(N:*|.[^.]*|..?*).

Zsh

Définissez l'option dot_glob .

% echo *
none zero
% setopt dot_glob
% echo *
..two .one none zero

. et .. ne sont jamais mis en correspondance, même si le modèle correspond explicitement au . de tête.

% echo .*
..two .one

Vous pouvez inclure des fichiers de points dans un modèle spécifique avec le qualificatif Dglob .

% echo *(D)
..two .one none zero

Ajoutez le qualificatif N glob pour que l'expansion soit vide dans un répertoire vide: *(DN).


Remarque: vous pouvez obtenir des résultats d'extension de nom de fichier dans différents ordres (par exemple, none suivi de .one suivi de ..two) en fonction de vos paramètres de LC_COLLATE, LC_ALL et LANG variables.

#!/bin/bash

shopt -s dotglob
mv Foo/* Bar/

De man bash

dotglob S'il est défini, bash inclut les noms de fichiers commençant par un '.' dans les résultats de l'expansion du nom de chemin.

24
SiegeX

Un moyen simple de le faire dans bash est

mv {Foo/*,Foo/.*} Bar/

Mais cela déplacera également les répertoires.

Si vous souhaitez déplacer tous les fichiers, y compris cachés, mais que vous ne voulez déplacer aucun répertoire, vous pouvez utiliser une boucle for et un test.

for i in $(ls -d {Foo/*,Foo/.*});do test -f $i && mv -v $i Bar/; done;

11
Boris Month

Une façon consiste à utiliser find:

find Foo/ -type f -exec mv -t Bar/ {} \+

Le -type f limite la commande find à la recherche de fichiers. Vous devriez enquêter sur le -type, -maxdepth, et -mindepth options de find pour personnaliser votre commande en fonction des sous-répertoires. Find a une longue mais très utile page de manuel .

4
Steven D

Essayez la commande de copie cp:

$ cp -r myfolder/* destinationfolder

cp -r signifie copier récursif, donc tous les dossiers et fichiers seront copiés.

Vous pouvez utiliser la commande de suppression rm pour supprimer un dossier:

$ rm -r myfolder

Voir plus: déplacer tous les fichiers d'un répertoire vers un autre .

2
ucefkh

Pour les distributions Linux minimales , ce qui suit devrait fonctionner. Tout d'abord, effectuez un mouvement de base tout (qui manque les fichiers cachés). Ensuite, déplacez tous les fichiers cachés (y compris le . et .. qui sera pas réellement déplacé).

mv /sourceDir/* /destinationDir 2> /dev/null
mv /sourceDir/.* /destinationDir 2> /dev/null

Notes: S'il n'y a pas de contenu visible, la première commande produira un message d'erreur. La deuxième commande toujours produira une erreur indiquant qu'elle ne peut pas se déplacer . et ... En tant que tel, canalisez simplement les erreurs dans /dev/null (comme montré).

Si vous en avez besoin comme doublure, combinez-les simplement avec un point-virgule:

mv /sourceDir/* /destinationDir 2> /dev/null; mv /sourceDir/.* /destinationDir 2> /dev/null
1
BuvinJ

Rsync est une autre option:

rsync -axvP --remove-source-files sourcedirectory/ targetdirectory

Cela fonctionne car dans rsync, la barre oblique de fin est importante, sourcedirectory/ fait référence au contenu du répertoire, tandis que sourcedirectory fait référence au répertoire lui-même.

L'inconvénient de cette méthode est que rsync ne nettoiera que les fichiers après le déplacement, pas le répertoire. Il vous reste donc une arborescence de répertoires d'origine vide. Pour des solutions de contournement, voir:

Déplacer des fichiers et supprimer des répertoires avec rsync?

Ainsi, bien que cela ne soit pas optimal pour les opérations de déplacement, il peut être extrêmement utile pour les opérations de copie.

1
Grumbel

Réponse pour bash/fish

Voici un moyen de le faire à l'aide de caractères génériques:

.[!.]* ..?* correspondra tous les fichiers cachés sauf . et ..

.[!.]* ..?* * correspondra tous les fichiers (masqués ou non) sauf . et ..

Et pour répondre à l'exemple particulier de cette question, vous avez besoin de cd foo && mv .[!.]* ..?* * ../bar

Explication

.[!.]* correspond aux noms de fichiers commençant par un point, suivi par n'importe quel caractère sauf le point éventuellement suivi par n'importe quelle chaîne. C'est assez proche mais il manque des fichiers commençant par deux points comme ..foo. Pour inclure de tels fichiers, nous ajoutons ..?* qui correspond aux noms de fichiers commençant par deux points, suivis de n'importe quel caractère, éventuellement suivi de n'importe quelle chaîne.

Test

Vous pouvez tester ces caractères génériques avec les commandes ci-dessous. Je les ai essayés avec succès sous bash et fish. Ils échouent sous sh, zsh, xonsh.

mkdir temp
cd temp
touch  a  .b  .bc  ..c  ..cd  ...d  ...de
ls .[!.]* ..?*
# you get this output:
          .b  .bc  ..c  ..cd  ...d  ...de
# cleanup
cd ..
rm -rf temp
1
ndemou

Je trouve que cela fonctionne bien pour bash et il n'est pas nécessaire de modifier les options Shell

mv sourcedir/{*,.[^.]*} destdir/

ÉDITER:

Donc, comme l'a déclaré G-man, ma réponse d'origine n'est pas conforme au posix et est à peu près la même que la réponse de ndemou ci-dessus avec un changement, qui consiste à utiliser l'expansion d'accolade pour créer des listes de chaînes qui sont ensuite mises à exécution. Cela signifie simplement que vous n'avez pas besoin de cd dans le répertoire source. Pas vraiment un grand changement, mais c'est différent.

exemple: supposons que vous ayez déjà la disposition suivante.

 $ tree -a
.
├── destdir
└── sourcedir
    ├── ..d1
    ├── ..d2
    ├── ..double
    ├── file-1
    ├── file-2
    ├── .hidden-1
    ├── .hidden-2
    ├── ...t1
    └── ...t2

La question d'origine ne mentionnait que les fichiers cachés avec une seule période, mais disons qu'il y en a avec deux ou plusieurs périodes au début du nom. Vous pouvez simplement ajouter une expression supplémentaire dans les accolades. On peut alors exécuter

mv sourcedir/{*,.[!.]*,..?*} destdir/

Cela se développe comme suit:

mv sourcedir/file-1 sourcedir/file-2 sourcedir/.hidden-1 sourcedir/.hidden-2 sourcedir/..d1 sourcedir/..d2 sourcedir/..double sourcedir/...t1 sourcedir/...t2 destdir/

Vous devriez maintenant voir tous les fichiers situés dans destdir :

 $ tree -a
.
├── destdir
│   ├── ..d1
│   ├── ..d2
│   ├── ..double
│   ├── file-1
│   ├── file-2
│   ├── .hidden-1
│   ├── .hidden-2
│   ├── ...t1
│   └── ...t2
└── sourcedir

Vous pouvez faire des choses assez cool avec des accolades en bash avec encore plus d'ajouts en 4.x. Consultez bash-hackers pour quelques exemples astucieux.

0
cmndr sp0ck

Vous pourriez également être en mesure de trouver et de grep avec des guillemets arrière pour sélectionner des fichiers pour la commande de déplacement. Passez-les en mv.

C'est à dire. Pour les fichiers cachés

find Foo -maxdepth 1 | egrep '^Foo/[.]' # Output: .hidden

Donc

mv `find Foo -maxdepth 1 | egrep '^Foo/[.]'` Bar # mv Foo/.hidden Bar

Déplace uniquement les fichiers cachés sélectionnés dans Bar:

mv `find Foo -maxdepth 1 | egrep '^Foo/.'` Bar # mv Foo/.hidden Foo/notHidden Bar

Déplace tous les fichiers de Foo vers Bar depuis le '.' dans la commande egrep agit comme un caractère générique sans les crochets.

Le ^ assure que la correspondance commence au début de la ligne.

Quelques détails sur egrep la correspondance des modèles peuvent être trouvés ici .

En utilisant maxdepth 1 empêche la recherche d'accéder aux sous-répertoires.

0
user3192145

Inspiré de cette réponse :

Sans copier les fichiers ...

rsync -ax --link-dest=../Foo/ Foo/ Bar

Mises en garde:

  • --link-dest le chemin doit être absolu ou relatif à DESTINATION (Bar dans l'exemple)

  • Vous devez mettre / après SOURCE (Foo/ dans l'exemple), sinon il copiera le dossier SOURCE au lieu de son contenu.

0
palindrom