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?

Léo Léopold Hertz 준영
la source

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/
qc
la source
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 준영
@UnixBasis, oui. Jetez un œil à gnu.org/software/bash/manual/html_node/Pattern-Matching.html
Juliano
@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.

Léo Léopold Hertz 준영
la source
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 \;
Johannes Schaub - litb
la source
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
John T
la source
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

Rohail Abbas
la source
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.

Juliano
la source
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
alex.pilon
la source
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.

Hlovdal
la source
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.

David Norman
la source
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.

David Z
la source
3
ls ~/Linux/Old/ | grep -v Tux.png | xargs -i {} mv ~/Linux/New/'
aitor
la source
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.

antibus
la source
3

On peut ignorer grep comme ceci:

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

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

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

Pakpoom Tiwakornkit
la source