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?

Chad Harrison
la source

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
se ruer
la source
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.

Tim
la source
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*
Michael Mrozek
la source
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.

MattBianco
la source
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).

utilisateur2707671
la source
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/

Edwin Lee
la source
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