Déplacer tous les fichiers sauf un


155

Comment puis-je déplacer tous les fichiers sauf un? Je recherche quelque chose comme:

'mv ~/Linux/Old/!Tux.png ~/Linux/New/'

où je déplace de vieux trucs vers un nouveau dossier sauf Tux.png. ! -sign représente une négation. Existe-t-il un outil pour le travail?

Réponses:


142

Si vous utilisez bash et que l' extgloboption shell est définie (ce qui est généralement le cas):

mv ~/Linux/Old/!(Tux.png) ~/Linux/New/

1
Je me suis trompé lorsque j'ai testé la commande pour de nombreux éléments: mv ~ / Linux / Old /! (Tux.png Tux1.png Tux2.png) ~ / Linux / New / Il vide tout l'ancien répertoire. Qu'est-ce qui ne va pas?
Léo Léopold Hertz 준영

5
@UnixBasics, essayez: ~ / Linux / Old /! (Tux.png | Tux1.png | Tux2.png)
Juliano

@Juliano Commande très cool! Y a-t-il plus d'opérations mathématiques comme OR et XOR? Je suppose qu'un tuyau est pour ET.
Léo Léopold Hertz 준영


@Juliano Je suis plutôt confus avec les modèles comme: mv ~ / Linux /? (Tux * .png) ~ / Linux / New / mv ~ / Linux / + (Tux * .png) ~ / Linux / New / Dans l'ancien , Je voulais déplacer 0-1 Tux -photo. Dans ce dernier, je voulais déplacer des photos 1-n Tux. Ils ont tout bougé. Pourquoi? Est-il possible de déplacer une quantité spécifique de photos?
Léo Léopold Hertz 준영

97

Mettez ce qui suit dans votre .bashrc

shopt -s extglob

Il étend les expressions rationnelles. Vous pouvez ensuite déplacer tous les fichiers sauf un par

mv !(fileOne) ~/path/newFolder

Exceptions par rapport aux autres commandes

Notez que, dans la copie de répertoires, le forward-flash ne peut pas être utilisé dans le nom comme remarqué dans le thread Pourquoi extglob sauf rupture sauf condition? :

cp -r !(Backups.backupdb) /home/masi/Documents/

c'est Backups.backupdb/faux ici avant la négation et je ne l'utiliserais pas non plus pour déplacer des répertoires à cause du risque d'utiliser à tort des globs avec d'autres commandes et d'autres exceptions possibles.


3
C'est en fait la bonne réponse. Le mien était complètement faux; heureusement, je l'avais utilisé dans un dossier avec seulement quelques fichiers. Voici plus d'informations sur la méthode que Masi montre: wiki.bash-hackers.org/syntax/pattern Allez dans "Langage de modèle étendu" et vous trouverez plus d'informations à ce sujet. Merci à @ paul-whittaker d'avoir signalé le problème.
mimoralea

C'est une vieille réponse mais elle est toujours valable. J'utilise Ubuntu 18 et extglob semble être activé par défaut (je ne l'ai pas choisi). J'ai utilisé la commande suivante pour déplacer tous les fichiers du répertoire actuel dans une archive qui se trouve également dans ce répertoire, sans inclure d'autres dossiers d'archive: mv !(arc*) archive_190629b
TonyG

70

J'irais avec la méthode traditionnelle find & xargs:

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png -print0 | 
    xargs -0 mv -t ~/Linux/New

-maxdepth 1fait qu'il ne recherche pas de manière récursive. Si vous ne vous souciez que des fichiers, vous pouvez dire -type f. -mindepth 1fait qu'il n'inclut pas le ~/Linux/Oldchemin lui-même dans le résultat. Fonctionne avec tous les noms de fichiers, y compris ceux qui contiennent des retours à la ligne intégrés.

Un commentaire note que l' -toption mv est probablement une extension GNU. Pour les systèmes qui ne l'ont pas

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png \
    -exec mv '{}' ~/Linux/New \;

1
Voté car il encourage l'apprentissage d'un outil puissant, trouvez. Remarque, pour les fichiers avec des espaces, cela ne fonctionnera pas. Considérez "find -print0 | xargs -0" ou bien renoncez à xargs: "find [ce que vous avez dit] -exec mv -t {} ~ / Linux / New \;"
JasonSmith

Si votre commande mv n'a pas l'option -t, alors utilisez "find ... -exec mv {} Linux / New \;" ou "find ... | xargs -I {} mv {} Linux / New". L'option -t semble être une extension GNU, ce qui est bien pour Linux, mais probablement pas ailleurs.
Rob Kennedy

jhs, oh j'échoue. Je pensais en quelque sorte que les xargs se divisaient aux nouvelles lignes mais pas aux espaces. on dirait que je l'ai confondu avec "read" :) mauvais le réparer
Johannes Schaub - litb

Un grand merci pour le conseil génial! J'allais choisir qc parce qu'il cible la question. Cependant, je peux sentir l'utilité de vos commandes plus tard, donc je dois choisir la manière "find and xargs". Ça bascule. Merci :)
Léo Léopold Hertz 준영

Chemin trop compliqué. La réponse Masi est plus complète, plus facile et donc plus correcte
user637338

30

Un moyen rapide serait de modifier le nom du fichier tux afin que votre commande de déplacement ne corresponde pas.

Par exemple:

mv Tux.png .Tux.png

mv * ~/somefolder

mv .Tux.png Tux.png

n'utilisez pas " . ", car cela ne déplacera que les fichiers qui ont un "." dans le nom. Juste "*" suffit.
Juliano

1
Si vous le changez en *, cela supprimera également votre fichier renommé.
John T

6
@John T: Non, le * glob ne correspond pas aux fichiers commençant par un point.
Bill Karwin

C'est de loin la meilleure réponse. Pas besoin de modifier ou de commenter cette réponse. 100 points. Merci beaucoup. Bien joué!
Steve K

23

Je pense que le moyen le plus simple est de faire des backticks

mv `ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Éditer:

Utilisez plutôt une barre oblique inverse avec ls pour éviter de l'utiliser avec un alias, c'est-à-dire que la plupart du temps, ls est aliasé comme ls --color.

mv `\ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Merci @Arnold Roa


1
Pouvez-vous expliquer pourquoi vous l'utilisez grep -v?
Léo Léopold Hertz 준영

1
L'option -v dans grep exclut le résultat, c'est comme prendre tout sauf Tux.png
Rohail Abbas

1
C'est certainement intuitif, mais les réponses ci-dessus sont meilleures. Si vous écrivez un script, par exemple, vous devez être dans le bon répertoire.
nJGL

@nJGL Nous pouvons également donner le chemin absolu ici, j'ai utilisé homedirectory (~) puisque la question avait ceci
Rohail Abbas

@RohailAbbas D'accord. ✌️
nJGL

14

Pour bash, la réponse est correcte. Voici la syntaxe zsh (mon shell de choix):

mv ~/Linux/Old/^Tux.png ~/Linux/New/

Nécessite que l' EXTENDED_GLOBoption shell soit définie.


3
Et si nous voulons exclure deux fichiers?
mpen

13

Je trouve que c'est un peu plus sûr et plus facile à utiliser pour les mouvements simples qui excluent certains fichiers ou répertoires.

ls -1 | grep -v ^$EXCLUDE | xargs -I{} mv {} $TARGET

C'est la meilleure solution pour Busybox / ASH
Stuart Cardall

1
Cela a fonctionné pour moi dans une situation où je devais déplacer tous les fichiers sauf quelques dossiers vers un autre répertoire
Umar Hayat

L' -loption de lsinclura beaucoup d'informations non pertinentes sur la ligne de commande et entraînera l'échec de la commande mv.
jdhao

5

Ce qui suit n'est pas une méthode garantie à 100% et ne doit pas du tout être tenté pour le script. Mais parfois, c'est assez bon pour une utilisation rapide du shell interactif. Un fichier global comme

[abc]*

(qui correspondra à tous les fichiers dont le nom commence par a, b ou c) peut être annulé en insérant d'abord un caractère "^", c'est-à-dire

[^abc]*

J'utilise parfois ceci pour ne pas correspondre au répertoire "lost + found", comme par exemple:

mv /mnt/usbdisk/[^l]* /home/user/stuff/.

Bien sûr, s'il y a d'autres fichiers commençant par l, je dois les traiter par la suite.


4
mv `find Linux/Old '!' -type d | fgrep -v Tux.png` Linux/New

La commande find répertorie tous les fichiers normaux et la commande fgrep filtre tout Tux.png. Les backticks indiquent à mv de déplacer la liste de fichiers résultante.


4
Jamais, jamais, n'évaluez find comme arguments pour une autre commande. De mauvaises choses vont arriver. Vous venez peut-être de créer une vulnérabilité. Utilisez toujours la commande find -print0 | xargs -0 construit, ou trouvez -exec.
Juliano

3

Que diriez-vous de tout déplacer dans le dossier et de simplement déplacer Tux.png en arrière?

Je ne peux penser à aucune syntaxe shell pour dire "tout sauf ..." à la légère.


3
ls ~/Linux/Old/ | grep -v Tux.png | xargs -i {} mv ~/Linux/New/'

1
Cette commande semble manquer une partie et ne fonctionne pas sur mon ordinateur. ls ~/Linux/Old/ | grep -v Tux.png | xargs -I{} mv {} ~/Linux/New/fonctionne à la place.
Katherine Chen

3

Que diriez-vous:

mv $(echo * | sed s:Tux.png::g) ~/Linux/New/

Vous devez cependant être dans le dossier.


3

On peut ignorer grep comme ceci:

ls ~/Linux/Old/ -QI Tux.png | xargs -I{} mv ~/Linux/Old/{} ~/Linux/New/

1

Cela pourrait être plus simple et facile à retenir et cela fonctionne pour moi.

mv $(ls ~/folder | grep -v ~/folder/exclude.png) ~/destination

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.