Question Comment copier récursivement des fichiers par extension de fichier, en préservant la structure des répertoires?


Sur la ligne de commande Linux, je voudrais copier un ensemble (très grand) de .txt fichiers d'un répertoire (et de ses sous-répertoires) à un autre.

J'ai besoin de la structure de répertoire pour rester intacte, et je dois ignorer les fichiers à l'exception de ceux se terminant par .txt.


66
2018-06-21 04:41


origine


Avoir cp et trouver comme balises dans votre question, cela signifie-t-il que vous êtes lié à ces options? Comme votre jeu de données est très volumineux, il est logique de supposer que le processus de copie peut être interrompu pour certaines raisons et que vous devrez le redémarrer. Je ne suis pas sûr que l'approche find / cp puisse reprendre le transfert et ne copier que la partie manquante. Si vous n'êtes pas lié à find / cp, vous pouvez envisager rsync, qui est plus intelligent. Son option --exclude vous permet d'ignorer les fichiers .txt. - vtest
Fair call - rsync est probablement la meilleure option. Pas lié à trouver / cp. (Je les ai quand même utilisés - rsync n’était pas installé sur la machine distante, c’était un serveur Web en direct et je voulais laisser une empreinte aussi petite que possible) - unclaimedbaggage


Réponses:


Vous pouvez utiliser trouver et cpio pour faire ça

cd /top/level/to/copy
find . -name '*.txt' | cpio -pdm /path/to/destdir

(-updm for overwrite destination content.)

88
2018-06-21 07:29



pourquoi M? Je pensais que c'était juste pour conserver la date de modification du fichier. - Mubashar Ahmad


cd /source/path
find -type f -name \*.txt -exec install -D {} /dest/path/{} \;

7
2018-06-21 08:13



Vous avez manqué un . après find. Aussi sur macOS 10.13.1, cela a fonctionné: find . -type f -name "*.txt" -exec install -v {} /dest/path/{} \; - grim


Une autre approche

find . -name '*.txt' -exec rsync -R {} path/to/dext \;


2
2018-01-18 02:31



J'aime cette solution. j'ai utilisé find . -iname '*.txt' -exec rsync -Rptgon {} path/to/dext \; pour faire une correspondance insensible à la casse et pour conserver la propriété et les autorisations. - MountainX


La façon la plus simple qui a fonctionné pour moi:

cp --parents -R jobs/**/*.xml ./backup/

une capture est que vous devez naviguer dans le répertoire "désiré" avant que le "chemin parent" soit correct.

Assurez-vous également que vous avez activé les globes récursifs dans bash:

shopt -s globstar

1
2017-09-11 21:21





que diriez-vous de le copier d'abord avec

cp -r /old/folder /new/folder

puis allez dans le nouveau dossier et exécutez

find . -type f ! -iname "*.txt" -delete

ou juste

cp -r /old/folder /new/folder && find . -type f ! -iname "*.txt" -delete

Edit: ok vous voulez une commande qui filtre (je n'ai pas testé cela parce que mon système n'a pas le cpio commander!). Voici où je l'ai trouvé: http://www.gnu.org/software/findutils/manual/html_mono/find.html#Copying-A-Subset-of-Files

find . -name "*.txt" -print0 |
     cpio -pmd0 /dest-dir

S'il vous plaît testez ceci en premier, car je ne l'ai pas encore essayé. Si quelqu'un vérifiait, ce serait formidable.


1
2018-06-21 05:03



hoche la tête Cheers - cela fonctionnerait, mais sans filtrage à .txt Je regarde quelques millions de fichiers (qui sortent à quelques centaines de Go). Si nécessaire, je devrais le faire, mais j'adorerais filtrer tout en copiant si possible - unclaimedbaggage
Bravo, la version éditée fonctionne si je retire le '0' de -pmd0 - unclaimedbaggage
Vous devriez garder le 0 dans -pmd0 et ajouter -print0 à la fin du find commande (juste avant la |). - G-Man


Accédez au répertoire:

cp '*.css' /path/to/destination

Vous devrez naviguer dans chaque dossier du répertoire, mais c'est mieux que la plupart des options que j'ai vues jusqu'ici.


-1
2017-10-20 20:29



Cette méthode n'est pas récursive, ce qui signifie que pour les grands répertoires, vous pouvez le faire pendant un bon moment ... - Iain Reid