Comment copier certains fichiers, mais pas tous?


54

Ainsi, vous pouvez utiliser le *comme un joker pour tous les fichiers lorsque vous l'utilisez cpdans le contexte d'un répertoire. Est-il possible de copier tous les fichiers sauf xfichier?

Réponses:


42

En bashvous pouvez utiliser extglob:

 $ shopt -s extglob  # to enable extglob
 $ cp !(b*) new_dir/

!(b*)exclure tous les b*fichiers.

Vous pouvez plus tard désactiver extglobavec

 $ shopt -u extglob

Savez-vous s'il y a quelque chose d'équivalent pour le shell tcsh?
Levon

Malheureusement non. On dirait que findc'est le seul moyen d'entrer tcsh:find . -maxdepth 1 ! -name "exclude*" -exec cp -t destination {} \+
Rush

50

Rsync s'en occupe bien.

Exemple copier tout: rsync -aP /folder1/* /folder/2

Exemple de copie avec exclusion: rsync -aP --exclude=x /folder1/* /folder2/

Le -aPcommutateur:

a: similaire à cp -a, récursif, etc. P: affiche les progrès, une fonctionnalité intéressante de rsync.


5
Et consultez cette réponse pour consulter un guide succinct des listes d’exclusion rsync courantes.
Gilles, arrête d'être méchant

1
Sur darwin / MacOS, utilisez -rPplutôt que -aPsi vous voulez recurse. -aest pour l'archivage. Vous ne savez pas si cela a changé ou si c'est simplement différent sous MacOS.
jpoveda

rsynca la possibilité de le rendre récursif. Exemple: rsync --recursive -P --exclude=x /folder1/* /folder2/. (Testé uniquement sur Ubuntu)
n1k31t4

12

Ce n'est pas une fonctionnalité de cp, c'est une fonctionnalité de votre shell (cela étend le terme *à tous les fichiers non-point), donc la réponse dépend du shell que vous utilisez. Par exemple, zshprend en charge cette syntaxe:

$ cp ^x /path/to/destination

^xsignifie "tous les fichiers sauf x"

Vous pouvez également combiner des modèles de sélection et de désélection. Par exemple, pour copier tous les fichiers wav sauf ceux contenant xyz, vous pouvez utiliser:

cp *.wav~*xyz*

Des commentaires sur bash?
Chad Harrison

@hydroparadise Je ne connais pas grand chose à propos de Bash, mais cette réponse semble couvrir tout cela
Michael Mrozek

Qu'en est-il de tcsh? Quelqu'un sait?
Levon

4

Pourrait également être utilisé dans une vieille coque simple (portable / compatible) de différentes manières avec des outils standard, de manière beaucoup moins élégante que dans une utilisation avancée de la coquille ou des commandes avec des options d'exclusion intégrées.

S'il n'y a pas trop de fichiers (et pas avec des noms comprenant des espaces et / ou des sauts de ligne), cela pourrait être un moyen:

cp `ls | egrep -v '^excludename$'` destdir/.

Bien sûr, les bashoutils GNU sont excellents et puissants, mais ils ne sont toujours pas disponibles. Si vous avez l'intention de le mettre dans un script portable, je le recommanderais findcomme dans le commentaire de Rush.


2
Je trouve que la dernière partie de votre réponse détourne simplement l'attention du sujet. En outre, "Unix" n'est plus la norme (si cela a déjà été le cas). Ce n'est tout simplement pas pertinent si quelque chose est "Unix" ou plus, alors que le titre de ce site est "Unix et Linux".
Alexandre

2
D'ACCORD. J'ai déplacé le commentaire ici: Unix n'est pas GNU. Je conviens que l’unicité des choses n’est pas très intéressante, mais je crois toujours en la portabilité et en connaissant un peu votre histoire.
MattBianco

Entièrement d'accord avec toi là-bas.
Alexander

2

Si vous souhaitez copier tout le contenu d'un dossier (y compris les sous-dossiers) dans un sous-répertoire particulier:

cp -R $(ls | grep -v '^subdir$') subdir/

Fonctionne avec sh, bash, zsh (au moins).


1
Convainquez-moi que ce n'est pas la même intention quecp -R * subdir/
roaima

1
Si vous utilisez cette commande "cp -R * sous-répertoire /", bash / zsh tente de copier "sous-répertoire" de manière récurrente. Vous vous retrouvez avec une erreur: "nom trop long (non copié)".
user2707671

Bon point. Votre suggestion tente d'éviter l'avertissement de cp(pas de bash/ sh), " cp: cannot copy a directory, ‘subdir’, into itself, ‘subdir/subdir’". La copie se termine correctement, cependant. Malheureusement, votre variante rompt avec tout nom de fichier contenant un espace ou une ponctuation sensible à un shell. Voir unix.stackexchange.com/q/128985/135943
roaima

-1

extglob est le meilleur moyen jusqu’à présent, je suppose.

Une autre façon utilise cp $(ls --ignore=x) subdir/


Cela cassera n'importe quelle forme de caractères spéciaux que ce soit dans les noms de fichiers. (Espaces, nouvelles lignes, $etc.) Ne jamais analyser la sortie de ls. unix.stackexchange.com/q/128985/135943
Wildcard
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.