Copie os arquivos de uma pasta para outra, mas tenha um intervalo entre cada arquivo

7

Existe uma maneira de copiar arquivos da pasta a para a pasta b, mas o processo é pausado por um segundo entre cada arquivo? Eu quero copiar um monte de arquivos para uma pasta watch, mas eu sei por experiência que se eu copiar todos eles de uma só vez (seja através do terminal cp ou GUI) ele vai fazer o meu rtorrent falhar ... Se eu pudesse copiar os arquivos com um segundo intervalo entre eles, isso daria ao rtorrent tempo para lidar com as coisas. Se eu pudesse fazer isso de um comando, isso me salvaria de fazer isso manualmente.

    
por zotteken 25.05.2018 / 21:27

2 respostas

10

Soluções de comando único

Entre muitas opções, incluindo loops que usam cp e sleep , podemos optar por find com dois -exec flags para executar esses comandos exatos.

find ~/dir_1/ -type f -maxdepth 1  -exec cp {} ~/dir_2 \;  -exec sleep 1   \;

Aqui as opções são:

  • ~/dir_1 , o diretório de origem, através do qual find funciona.
  • -type f obtém apenas arquivos
  • -maxdepth 1 desce 1 nível máximo na árvore de diretórios; impede a descida em subdiretórios
  • -exec cp {} ~/dir_2 \; copia o arquivo atualmente processado designado pelo parâmetro {} para ~/dir_2 . O \; designa cp para processar um único arquivo por vez, em vez de colocar tantos arquivos quanto possível em {} . A barra invertida em \; é necessária para evitar que o shell interprete erroneamente isso como terminador de comando.
  • exec sleep 1 \; executa sleep 1 por cada arquivo atual.

Se você tem uma lista de arquivos em um arquivo, você pode fazer:

xargs -I % --arg-file=input.txt sh -c 'cp % ~/dir_2/ ;sleep 1'

As opções aqui são:

  • -I % designa o símbolo que se refere ao arquivo dentro do comando
  • --arg-file=input.txt lê argumentos para o comando de um arquivo específico
  • sh -c 'cp % ~/dir_2/ ;sleep 1' execute /bin/sh com os comandos fornecidos por -c '...' flag; % será substituído pelo nome do arquivo.

Soluções de loop

Você poderia usar um loop for por exemplo

for f in "/path/to/folder_1"/*; do
    cp "$f"  "/path/to/folder_2/"
    sleep 1
done

Para maior clareza, isso é formatado em várias linhas, mas também funciona como uma única linha. Você também pode transformar isso em uma função:

delaycp(){
    for f in "$1"/*; do
        cp "$f"  "$2"/
        sleep 1
    done
}

E use-o como

delaycp "/path/to/folder1" "/path/to/folder2"

Alternativamente, se você deseja copiar apenas certos arquivos, não todos que * glob captura no diretório, você sempre pode fazer uso da expansão do nome do caminho, algo como file{1..25} , ou ter um arquivo de texto de entrada, algo como este input.txt :

/path/to/folder_1/file1
/path/to/folder_1/file2
/path/to/folder_1/file3

E a partir disso, use while IFS= read -r line structure para ler o arquivo:

while IFS= read -r line || [ -n "$line" ]; do
    cp "$line" "/path/to/folder_2/${line##*/}"
    sleep 1
done < input.txt
    
por Sergiy Kolodyazhnyy 25.05.2018 / 21:31
2

com parallel

Aqui está uma parallel solução,dêosargumentosparaparallelcom:::exatamentecomocomcpouuseumalistadearquivos:

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

A opção -j informa parallel para executar apenas 1 trabalho de uma só vez, em vez de executar trabalhos em paralelo, as aspas simples simplesmente contêm o script em que {} é substituído pelo arquivo atualmente processado e ::: ou :::: introduza a lista de argumentos ou arquivo (s) respectivamente. Veja man parallel para muito mais.

com find -exec

find fornece uma maneira conveniente de executar comandos nos resultados, por exemplo para copiar todos os arquivos .log dentro e abaixo do diretório atual:

find -name "*.log" -exec sh -c 'cp "$0" /path/to/dir2/;sleep 1' "{}" \;
    
por dessert 26.05.2018 / 08:10