Comment déplacer tous les fichiers du répertoire actuel vers le répertoire supérieur?


133

Comment déplacer tous les fichiers du répertoire actuel vers le répertoire supérieur de linux?

J'ai essayé quelque chose comme ça mv *.*, mais ça ne marche pas.


Je n'ai pas assez de représentants pour repasser les questions, mais puis-je suggérer [linux] [mv] [cwd] [files], ou quelque chose de similaire?
Stephan202

J'ai retagué cette question à la demande de Stephan202.
eleven81

Réponses:


202

La commande que vous recherchez est

mv * .[^.]* ..

ou (voir ci-dessous pour plus d'informations):

(shopt -s dotglob; mv -- * ..)

Explication: la mvcommande déplace des fichiers et des répertoires. Le dernier argument de mvest la cible (dans ce cas, le répertoire un pas "en haut" dans l'arborescence ..). Les arguments précédents sont les fichiers source et les répertoires. L'astérisque ( *) est un caractère générique qui correspond à tous les fichiers qui ne commencent pas par un point. Les fichiers commençant par un point (fichiers de points) sont "cachés". Ils sont appariés en utilisant le motif .[^.]*(voir édition ci-dessous).

Voir la page de manuel que j'ai liée pour plus d'informations mv.


Pourquoi .[^.]*au lieu de .*?

Comme Chris Johnsen souligne à juste titre : le modèle .*correspond également .et ... Puisque vous ne voulez pas (et ne pouvez pas) les déplacer, il est préférable d'utiliser un modèle qui correspond à tout nom de fichier commençant par un point sauf ces deux . Le modèle .[^.]*ne fait que cela: il correspond à n'importe quel nom de fichier (1) commençant par un point (2) suivi d'un caractère qui n'est pas un point (3) suivi de zéro ou de plusieurs caractères arbitraires.

Comme Paggas souligne , il faudrait aussi ajouter le modèle .??*afin de faire correspondre les fichiers commençant par deux points. Voir sa réponse pour une solution alternative en utilisant find.

La réponse d'Arjan mentionne shoptpour éviter tous ces problèmes avec les fichiers de points. Mais il reste le problème des fichiers commençant par un tiret. Et cela nécessite trois commandes. Pourtant, j'aime bien l'idée. Je propose de l'utiliser comme ceci:

(shopt -s dotglob; mv -- * ..)

Ceci s'exécute shoptdans un sous-shell (donc pas de deuxième appel à shoptrequis) et utilise --pour que les fichiers commençant par un tiret ne soient pas interprétés comme des arguments mv.


7
L'utilisation .*peut provoquer que mv produise des avertissements / des erreurs indiquant qu'il est impossible de déplacer .et ... Vous pourriez essayer à la mv * .[^.]* ..place.
Chris Johnsen

1
@alain: vous êtes les bienvenus, et bienvenue sur le site! (Si (et seulement si) l'un des messages ici répond suffisamment à votre question, vous pouvez le marquer comme tel. Cela donnera à l'affiche 15 points de réputation supplémentaires et vous donnera également 2 représentants en plus.)
Stephan202

J'aime beaucoup la solution shopt qui s'exécute dans une sous
coque

2
Il n'y a pas de mal à utiliser la syntaxe *. * - inclure .. n'est dangereux que lorsqu'il est utilisé avec chmod et chown et avec l'indicateur "recurse", c'est-à-dire chmod -R ou chown -R. Et dans ces cas, ne tapez jamais chown. * Ou chmod. * - chown le répertoire principal dans le chemin que vous recherchez et utilisez -h (ne suivez pas les liens symboliques). Mais, mv .. ne fait tout simplement rien alors ne vous inquiétez pas pour ça.
chris

1
Les trois modèles corrects sont *, .[^.]*et ..?*. La seconde peut-être .[!.]*pour les coquilles plus anciennes (POSIX). Lire aussi

42

Réponse courte: utiliser

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

Longue réponse:

La commande

mv * .* ..

ne fonctionnera pas car .*peut correspondre .et ... Mais la commande

mv * .[^.]* ..

ne fonctionnera pas non plus, car .[^.]*ne correspondra pas, par exemple ..filename! Au lieu de cela, ce que je fais est

mv * .[^.] .??* ..

qui correspondra à tout sauf .et ... *correspond à tout ce qui ne commence pas par un ., .[^.]correspond à tous les noms de fichiers de 2 caractères commençant par un point sauf .., et .??*correspond à tous les noms de fichiers commençant par un point d'au moins 3 caractères.

Mieux encore, vous pouvez utiliser

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

qui évite les horribles hacks glob dans mv * .[^.] .??* ..!


1
De plus, j'ai oublié de noter l'importance de - pour que la commande fonctionne correctement avec les noms de fichier commençant par un tiret. J'ai inclus - dans ma réponse à la recherche cependant. Une réponse plus complète en utilisant globs est "mv - *. [^.]. ?? * *".
Paggas

+1: Je suis revenu ajouter ..?*à mon commentaire et vous en aviez déjà pris soin.
Chris Johnsen

1
Que peut-être peut-être mal avec essayer de mv ..? Il ne fait simplement rien et ne peut rien faire. Il y a d'autres commandes où il peut faire quelque chose (chmod et chown) mais mv et rm ne font tout simplement rien. ou ..
chris

1
Cela donne mv: option illégale - t
pal4life

1
Bono, les doubles tirets indiquent mvd'arrêter de chercher d'autres options de commande. Les accolades sont un nom de fichier résultant. Le signe plus indique au lieu d'exécuter exec par résultat (c'est-à-dire par nom de fichier), placez autant de résultats que possible dans un seul exec. Par souci d'exhaustivité, -t..indique à move de déplacer la destination cible vers laquelle déplacer tous ces fichiers.
Isuldor

14

Juste pour être complet, on peut aussi dire au shell Bash d'inclure des fichiers cachés, en utilisant shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob

+1 Beaucoup plus propre. Je pense cependant qu’une légère amélioration est nécessaire. Voir la mise à jour de ma réponse.
Stephan202

8

Le mv n'a pas la fonctionnalité de déplacement de fichiers cachés lors de l'utilisation *- alors pourquoi ne pas utiliser la copie à la place?

cp -rf . ..

rm -rf *

Pas besoin d'entrer dans les solutions complexes de dotglobbing et d'utiliser des commandes de recherche.


Avertissement Si vous vous déplacez dans le même système de fichiers , dans la plupart des cas, vous n'avez pas vraiment copié les fichiers, mais seulement mis à jour les entrées du répertoire sans déplacer les contenus d'inode ou de fichier. Voir même [1 ]. Avec a cpet rmau lieu de cela, vous copiez vraiment tout.
Hastur

6
rsync -a --remove-source-files . ..

rsync est un outil de copie de fichiers extrêmement puissant, généralement utilisé pour effectuer des sauvegardes et des miroirs incrémentiels efficaces à distance.

Avec la commande ci-dessus, nous demandons rsyncde copier le contenu de .dans..

Le commutateur -aactive la récursion dans les .sous-répertoires et active d'autres options courantes.

Le commutateur --remove-source-filesdemande à rsync de supprimer les fichiers source après une copie réussie, c’est-à-dire qu’il fait se comporter de la même manière que la mvcommande.


1
Un peu plus d'explication serait bien.
ChrisF

Bien sûr, espérons que ce sera plus clair maintenant.
mrucci

Notez que --remove-source-filescela ne supprimera pas les annuaires (synchronisés).
Dennis

Belle solution acceptée me donne une -bash: /bin/mv: Argument list too longerreur. Celui-ci fonctionne comme le charme.
userlond

2

En fin de compte, les tentatives mv .échoueront car mv ne pourra pas dissocier le répertoire dans lequel vous vous trouvez. Vous pouvez mv * ..déplacer les fichiers dans le dossier de cwd.


2
mv * .??* ../.

*obtient tous les fichiers non-point. .??*obtient tout. fichiers au moins trois octets de long, ce qui fonctionne pour tous les légitimes. Tout ce que vous voulez, vous voulez probablement rmplutôt que de mvtoute façon.

La ../.n'offre aucun avantage direct sur ..mais en faisant un mouvement à ce répertoire est une très bonne habitude à prendre, car il échouera, comme vous voulez, s'il y a quelque chose de mal avec le chemin. Par exemple, mv xyz bletchlorsque vous pensez bletch être un répertoire, vous pouvez en savoir plus avec mv xyz bletch/..


2
Vous pourriez ajouter .[^.]pour obtenir des fichiers de couverture comme .a.
Chris Johnsen

Il n'y a pas de différence entre ../ et ../. donc je ne prendrais pas la peine de taper le. après la barre oblique. De plus, dans le cas de mv et rm, l'inclusion ne fait aucun mal. et .. dans la liste, c’est-à-dire qu’il n’ya rien d’effrayant avec mv *. * / chemin / vers / fichier /, comme rm. ou même -rf. ne fait rien.
chris

2

Cette commande minimisée fonctionne sur la plupart des coques modernes:

\mv -- {,.{[^.],??}}* ..

Sinon mentionné est une solution portable:

\mv -- * .[^.] .??* ..

Fonctionnalités:

  1. \ empêche les alias de modifier mv de manière indésirable.

  2. - empêche les noms de fichiers contenant des tirets (-xyz) d'être interprétés comme des arguments de ligne de commande.

  3. . [^.] correspond aux noms de fichiers de deux caractères commençant par. sauf ..

  4. . ?? * correspond à tous les autres noms de fichiers de trois caractères ou plus.

Implémentations naïves:

  1. Ce qui suit ignore les noms de fichiers UNIX cachés, ceux qui commencent par. (.bashrc).

    mv * ..
    
  2. Les correspondances suivantes .. qui tentent de manière récursive de déplacer tous les répertoires éventuellement jusqu’à / dans .. du répertoire de travail en cours ($ PWD ou pwd). Ne jamais utiliser.

    mv .* ..
    

2

Il est plus correct d'utiliser ce modèle * .[!.] .??*que * .[^.] .??*celui-ci fonctionnant également avec les anciens shell tels que ksh88:

mv -- * .[!.] .??* ..
  • -- évite les problèmes lorsque vous avez un nom de fichier qui commence par -
  • * correspond à tous les noms de fichiers qui ne commencent pas par un .
  • il n'y a pas de noms de fichier de caractère commençant par un .que vous pouvez / devez déplacer
  • .[!.] correspond à tous les noms de fichier de deux caractères qui commencent par un .
  • .??* correspond aux noms de fichiers à trois caractères (ou plus longs) commençant par un .

Avec ksh88, le modèle de nom de fichier correspond .[^.]en fait aux noms de fichier ..(qui existent toujours) et .^(qui n'existe probablement pas), ce qui a un effet opposé à celui souhaité.


0

Trouve et travaille aussi. Ce type de structure peut être utile si vous souhaitez sélectionner des fichiers sur des critères plus complexes en modifiant find et egrep.

find -maxdepth 1 | egrep '^./.'         # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..

0

Je pense que la solution la plus simple pour déplacer tous les fichiers dans son répertoire parent. serait

mv "`ls`" ../

ou, s'il y a des fichiers / répertoires cachés

utilisation:

mv "`ls -a`" ../ 2>/dev/null

En outre, supposons que vous souhaitiez déplacer le contenu d’un dossier dans l’un de ses dossiers internes (par exemple)

utilisation:

mv "`ls -a`" /tony 2>/dev/null

Remarque:

"`ls -a`" 

Pour déplacer les fichiers contenant des espaces.

2>/dev/null

Permet de supprimer l'avertissement / l'erreur, car ls -ale dossier .et sera également imprimé ..et vous ne pouvez ni les déplacer ni les copier. Donc, pour ces dossiers, une erreur s’affichera (si nous n’utilisons pas 2> / dev / null), il ne pourra pas les déplacer et le reste sera déplacé assez facilement.

Il est préférable d'éviter ls -as'il n'y a pas de fichiers cachés et simplement de les utiliser ls.


Avez-vous essayé ce qui va arriver quand vous courez mv $(ls -a)? Cela taperait sur le répertoire en cours et le répertoire en dessous de celui-ci, car ls -aaffichera ..également.
Sami Laine

Merci, @SamiLaine pour la suggestion que j'ai apportée les corrections. Mais mv ls -a ../cela aurait également fonctionné selon les besoins. Oui, il affichera ces erreurs comme indiqué ci-dessus, mais à part cela, il déplacera les dossiers / fichiers requis dans le répertoire parent.
Prabhat Kumar Singh

Cela ne fonctionnera pas pour les fichiers avec des espaces.
Kenorb

@kenorb, vous devez doubler la lscommande pour déplacer les fichiers avec des espaces. J'ai apporté les modifications requises. Merci d'avoir signalé.
Prabhat Kumar Singh
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.