Existe-t-il un moyen de copier des fichiers d'un dossier a vers un dossier b mais de laisser le processus s'interrompre une seconde entre chaque fichier? Je veux copier beaucoup de fichiers dans un dossier de contrôle, mais je sais par expérience que si je les copie tous en même temps (via le terminal cp ou l'interface graphique), mon plantage réel se bloquera ... Si je pouvais copier les fichiers avec un second intervalle entre eux, cela donnerait à torrent le temps de gérer les choses. Si je pouvais le faire à partir d'une commande, cela m'éviterait de le faire manuellement.
Parmi les nombreuses options, y compris les boucles qui utilisent cp
et sleep
, nous pourrions opter pour find
avec deux drapeaux -exec
pour exécuter ces commandes exactes.
find ~/dir_1/ -type f -maxdepth 1 -exec cp {} ~/dir_2 \; -exec sleep 1 \;
Ici les options sont:
~/dir_1
, le répertoire d'origine, par lequel find
fonctionne.-type f
récupère uniquement les fichiers-maxdepth 1
descends d'un niveau maximum dans l'arborescence de répertoires; empêche la descente dans les sous-répertoires-exec cp {} ~/dir_2 \;
copie le fichier en cours de traitement désigné par le paramètre {}
dans ~/dir_2
. Le \;
indique que cp
doit traiter un fichier à la fois au lieu de placer autant de fichiers que possible dans {}
. La barre oblique inversée dans \;
est nécessaire pour empêcher Shell d'interpréter cela de manière erronée en tant que terminateur de commande.exec sleep 1 \;
exécute sleep 1
pour chaque fichier en cours.Si vous avez une liste de fichiers dans un fichier, vous pouvez faire:
xargs -I % --arg-file=input.txt sh -c 'cp % ~/dir_2/ ;sleep 1'
Les options ici sont:
-I %
désigne le symbole faisant référence à un fichier dans la commande--arg-file=input.txt
lire les arguments d'une commande à partir d'un fichier spécifiquesh -c 'cp % ~/dir_2/ ;sleep 1'
exécuter /bin/sh
avec les commandes fournies par -c '...'
flag; %
sera remplacé par nom de fichier.Vous pouvez utiliser une boucle for par exemple
for f in "/path/to/folder_1"/*; do
cp "$f" "/path/to/folder_2/"
sleep 1
done
Pour des raisons de clarté, ceci est formaté sur plusieurs lignes, mais cela fonctionne tout aussi bien comme une seule ligne. Vous pouvez aussi transformer cela en une fonction:
delaycp(){
for f in "$1"/*; do
cp "$f" "$2"/
sleep 1
done
}
Et l'utiliser comme
delaycp "/path/to/folder1" "/path/to/folder2"
Alternativement, si vous voulez copier uniquement certains fichiers, pas tout ce que *
glob capture dans le répertoire, vous pouvez toujours utiliser le développement du chemin, quelque chose comme file{1..25}
, ou avoir un fichier texte d'entrée, quelque chose comme ceci input.txt
:
/path/to/folder_1/file1
/path/to/folder_1/file2
/path/to/folder_1/file3
Et à partir de là, utilisez la structure while IFS= read -r line
pour lire le fichier:
while IFS= read -r line || [ -n "$line" ]; do
cp "$line" "/path/to/folder_2/${line##*/}"
sleep 1
done < input.txt
parallel
Voici un parallel
solution, donnez les arguments à parallel
avec :::
exactement comme avec cp
ou utilisez une liste de fichiers:
parallel -j1 'cp {} /path/to/dir2/;sleep 1' ::: /path/to/dir1/* # or
parallel -j1 'cp {} /path/to/dir2/;sleep 1' :::: /path/to/file_list.txt
L'option -j
indique à parallel
de n'exécuter que le travail 1
à la fois plutôt que d'exécuter les travaux en parallèle. Les guillemets simples contiennent simplement le script dans lequel {}
est remplacé par le travail en cours. file et :::
ou ::::
introduisent respectivement la liste d'arguments ou le fichier. Voir man parallel
pour beaucoup plus.
find -exec
find
fournit un moyen pratique d'exécuter des commandes sur les résultats, par exemple. pour copier chaque fichier .log
dans et sous le répertoire actuel, procédez comme suit:
find -name "*.log" -exec sh -c 'cp "$0" /path/to/dir2/;sleep 1' "{}" \;