Classifique e copie arquivos de vários diretórios

0

Eu tenho um diretório contendo vários subdiretórios, contendo arquivos.

Eu gostaria de classificar os arquivos em cada um desses diretórios pelo nome em ordem alfabética e copiar o primeiro arquivo de cada diretório para um novo diretório.

  • Eu gostaria de ignorar arquivos ocultos.
  • Se houver um arquivo com o mesmo nome no diretório de destino, os dois arquivos devem ser mantidos.

Amostra:

parentdir
->dir1
    ->afile
    ->bfile
    ->cfile
->dir2
    ->dfile
    ->efile
    ->ffile
->dir3
    ->afile
    ->hfile
    ->ifile

Eu gostaria de executar um comando que preencheria meu novo diretório da seguinte forma:

newdir
->afile
->afile.1
->dfile

Como isso pode ser feito?

    
por dekatch 24.12.2017 / 14:14

3 respostas

0

Eu acho que a maneira direta é usar ls para listar os arquivos, o que ele faz em ordem alfabética (e omitindo arquivos ocultos) por padrão, pegar o primeiro de cada diretório com head , e então ter um Um pouco de código shell para descobrir o nome do arquivo para o qual eles devem ser copiados. Como neste script bash:

for d in ./*/; do
    src="$(ls "$d" | head -n 1)"
    dstbase="newdir/$(basename "$src")"
    if [[ ! -f "$dstbase" ]]; then
        cp "$src" "$dstbase"
    else
        suffix=1
        while [[ -f "$dstbase.$suffix" ]]; do
            let suffix++
        done
        cp "$src" "$dstbase.$suffix"
    fi
done

Obviamente, você terá que ajustar os caminhos de arquivo conforme necessário para sua situação atual. Isso também é bastante frágil no sentido de que pode haver problemas se houver diretórios em dir1 , dir2 , etc. que você deseja excluir da cópia. Ele também tem uma condição de corrida potencial no loop que procura um nome de arquivo não utilizado; isso provavelmente não será um problema, mas não faça nada como executar várias cópias disso em paralelo.

    
por 25.12.2017 / 00:04
0

Isso pode ser alcançado com a seguinte linha:

ls -ltr /parent_directory_path/ |
awk '$1~"^drw" {print $9}' |
while read line; do
  ls -l $line |
  awk '$1 ~ "^-r" {print $9}' |
  head -1 |
  awk -v line="$line" '{print "cp -rvfp"  "  " line"/"$1 " " "/newdir/" }';
done |
sh
    
por 25.12.2017 / 07:58
0

Com zsh e GNU cp :

cd parentdir &&
  for dir (*(/)) (cp --backup=numbered -- $dir/*(.[1]) newdir/)

o --backup=numbered implementa um esquema de backup no qual os arquivos são nomeados file.~1~ , file.~2~ ... Assim, a primeira cópia será file.~max~ e a última file (processará a lista para trás)*(/On) em vez de *(/) ) se você quiser que a ordem seja invertida.

POSIXly, você poderia fazer:

cp_numbered() (
  suffix=
  n=0
  while [ -e "$2$suffix" ] || [ -L "$2$suffix" ]; do
    suffix=.$((n += 1))
  done
  exec cp -- "$1" "$2$suffix"
)
cd parentdir &&
  for dir in */; do
    for file in "$dir"/*; do
      if [ -f "$file" ]; then
        cp_numbered "$file" "newdir/${file#*/}"
        continue 2
      fi
    done
  done
    
por 05.01.2018 / 15:02

Tags