Como faço para mover todos os arquivos com o mesmo nome espalhados pelo sistema de arquivos em uma pasta?

5

Eu tenho uma árvore de sistema de arquivos e em locais diferentes dentro dela estão arquivos com o mesmo nome. Eu tentei o seguinte comando na linha de comando:

find / -name "HAHA" -exec mv {} /home \;

Funcionou apenas para um arquivo, para os outros, recebi uma mensagem de erro por ter o mesmo nome.

Posso alterar o comando de forma que, para cada nome de arquivo, um número seja anexado para distingui-los?

    
por Abdul Al Hazred 14.02.2015 / 15:42

3 respostas

4

Eu encontrei uma solução simples com um pequeno script. O script é chamado cpf (ou qualquer outro nome que você dê) e é o seguinte:

#!/bin/bash

dir=xyz       # Directory where you want the files
num=1

for file in "$@"
do
    base='basename -- "$file"'
    mv -- "$file" "$dir/$base.$num"
    num=$(($num+1))
done

Você executa o comando da seguinte forma:

find . -name HAHA -print0 | xargs -0x cpf
    
por 14.02.2015 / 16:57
9

Posso pensar em duas soluções possíveis:

  1. Se você instalou mv de GNU coreutils (que provavelmente é o caso), então o seguinte comando ...

    find / -name "HAHA" -type f -exec mv --backup=numbered "{}" /home \;
    

    ... moverá todos os arquivos chamados HAHA para /home . A opção --backup=numbered de mv garante que todas as Quando o comando mv for executado, ele verificará se já existe um arquivo chamado HAHA no diretório de destino - e, se ele existir, primeiro renomeia para HAHA.~n~ (onde n é um número crescente ) antes de mover o novo arquivo para o /home . No final, você terá arquivos com o nome HAHA , HAHA.~1~ , HAHA.~2~ etc. em /home .

  2. Este script de shell deve funcionar, mas não é resistente a caminhos que contêm novas linhas:

    IFS="
    "      # if you are using bash, you can just use IFS=$'\n' here
    i=1
    for file in $(find / -name "HAHA" -type f); do
      mv "${file}" "/home/HAHA${i}"
      i=$((${i} + 1))
    done
    

    Isso itera sobre todos os arquivos HAHA e move cada um deles para /home/HAHAn , onde n novamente é um número crescente, começando com 1.

por 14.02.2015 / 16:53
3

Eu usaria while loop:

i=1
find / -name 'HAHA' -print0 | while read -d '' -r file; do mv "$file" "/home/${file##.*/}$((i++))"; done

Importante aqui é a opção print0 de find que (juntamente com a opção -d '' de read ) trata corretamente os arquivos com espaços em branco em seus nomes. Se você precisar fazer tal operação apenas uma vez, então a primeira linha que definir i=1 não será necessária, pois bash (e a maioria das outras camadas) simplesmente criará essa variável automaticamente.

    
por 14.02.2015 / 17:11