copy n número de arquivos de uma pasta para outra pasta

1

Eu tenho uma pasta com n números de arquivos. Eu preciso mover n / 2 (ou) n / 3 arquivos dessa pasta para qualquer outra pasta. Como definir o valor de n para que ele mova exatamente o número de arquivos?

    
por dino 19.11.2014 / 18:14

3 respostas

3

Você poderia fazer algo como

k=1; find source/ -type f | while read file; do
     [[ k++ -le 20 ]] && cp "$file" target/ 
done

Isso localizará todos os arquivos no diretório atual e copiará os 20 primeiros que encontrar para target/ . O truque é a variável $k , que é inicializada em 1 . Então, o [[ k++ -le 20 ]] && cp significa "Se $ k mais um for menor ou igual a 20, execute o comando cp".

O texto acima será quebrado se os nomes dos arquivos contiverem espaços, novas linhas ou outras estranhezas. Se isso pode ser um problema, use esta versão mais segura:

k=1; find source/ -type f -print0 | 
    while IFS= read -d '' -r file; do 
        [[ k++ -le 20 ]] && cp "$file" target/ 
    done

Se você não precisa descer em subdiretórios, apenas faça

k=1; for file in *; do [[ k++ -le 20 ]] && cp "$file" target/ ; done

Finalmente, para calcular n on the fly, você pode fazer (observe que isso também contará subdiretórios)

files=( * ); ## save all files in the current directory in an array
n=$(echo "${#files[@]} / 3 " | bc) ## get the value of n/3
for file in "${files[@]:1:$n}"; do cp "$file" bar/; done

A solução acima deve funcionar com nomes de arquivos arbitrários, incluindo os que incluem novas linhas.

    
por terdon 19.11.2014 / 18:40
2

Use uma combinação de find , sed e xargs :

find /path/to/dir -print0 | sed -nz '1~2p' | xargs -0 cp --target-dir=/some/dir

sed -n '1~2p' imprime todas as linhas alternativas, reduzindo assim a contagem para metade. Para torná-lo um terceiro, use 1~3p . As opções -print0 , -z e -0 indicam que estamos usando o caractere %code% (NULL) para delimitar as coisas.

Referências:

por muru 19.11.2014 / 18:55
2

Para fazer uma fração (por exemplo, & frac13;) sem saber a contagem antecipadamente,

k=0; for file in *
do
    if [ $((k++ % 3)) -eq 0 ]
    then
        mv "$file" target/
    fi
done

Isso vai pegar cada terceiro arquivo, mantendo um contador em execução ( k ) e agindo em cada arquivo para o qual k é um múltiplo de 3. Desde que comecei o contador em 0, isso será arredondado; Por exemplo, se você tiver dez ou onze arquivos (ou doze), ele moverá quatro deles.

Se houver subdiretórios (ou arquivos exóticos, como FIFOs) no diretório atual, e você quer mover ⅓ dos arquivos simples , deixando os outros em paz, mude o acima para

k=0; for file in *
do
    if [ -f "$file" ]  &&  [ $((k++ % 3)) -eq 0 ]
    then
        mv "$file" target/
    fi
done

Se você quiser descer em subdiretórios, diga

shopt -s globstar

e use ** em vez de * . Se você quiser incluir nomes que começam com um ponto ( . ), você também deve shopt -s dotglob .

A solução acima deve funcionar com nomes de arquivos arbitrários, incluindo os que incluem novas linhas.

    
por G-Man 19.11.2014 / 22:38