para o loop para preceder o nome do dir para os nomes dos arquivos

0

Eu sei que esse tópico já foi abordado (de alguma forma aqui e também em outro lugar), mas eu lhe imploro indulgência porque estou tentando encontrar meu caminho através da arte de script do bash;

Eu preciso resolver o seguinte problema

dado que eu tenho:

dir1

  • arquivo 1
  • arquivo 2
  • e assim por diante ...

dir2

  • file1
  • arquivo2
  • e assim por diante ...

Eu quero renomear arquivos para que

dir1

  • dir1_file 1
  • dir1_file 2
  • dir1_e assim por diante ...

dir2

  • dir2_file1
  • dir2_file2
  • dir2_e assim por diante ...

até agora consegui elaborar o seguinte script bash "exploratório"

for d in 'ls -d */'
 do
   #echo "$d"
   pre="${d:0:-1}"
   #echo "$pre"
   #cd "${d}"
   pushd "${d}"
    for f in *.jp2
     do
        #echo "${f}"
        echo "${pre}_${f}"
     done
   #cd - 
   #popd    
 done

parece funcionar bem, exceto pela mensagem de erro

line 9: pushd: dir2/: No such file or directory

onde dir2 é o nome do último diretório sendo varrido pelo loop for ...

alguma ajuda para isso? o que eu sinto falta?

    
por maxbre 06.10.2017 / 11:56

2 respostas

0

Em vez de tentar cd para trás e para frente em diretórios ( popd e pushd são principalmente para uso interativo, de qualquer maneira):

#!/bin/sh

for name in */*; do
    [ ! -f "$name" ] && continue

    dir="$( basename "$( dirname "$name" )" )"
    newname="$dir/${dir}_${name##*/}"

    if [ ! -e "$newname" ]; then
        echo mv "$name" "$newname"
    fi
done

Isso itera sobre todos os nomes em todos os diretórios no diretório atual. Ele ignorará os arquivos que não foram arquivos e extrairá o nome de base do diretório (o nome do diretório sem caminho) em dir . Em seguida, ele constrói um novo nome de arquivo, $newname , para o arquivo usando $dir e a parte de nome de base do nome do caminho em $name ( ${name##*/} pode ser substituída por $( basename "$name" ) ).

Se o novo nome ainda não tiver sido recebido, o arquivo será renomeado.

Remova o echo para realmente renomear os arquivos depois de verificar se ele deve fazer a coisa certa.

Para executar um conjunto de ações em outro diretório e depois voltar, use

( cd dir
  action
  action 
  action )

O diretório alterado não influencia o ambiente fora do ( ... ) .

Veja também: Por que * not * pars 'ls'?

    
por 06.10.2017 / 12:08
0

Você diz "dir2 é o nome do último diretório que está sendo varrido pelo loop for", mas na verdade é o segundo e por último, não é? Está falhando porque você tem o popd comentado. No final da primeira iteração do loop, você ainda está "em" dir1 , Portanto, sua tentativa de pushd dir2 está realmente procurando por dir1/dir2 ; ou seja, dir2 dentro de dir1 .

Se você tem sete diretórios, ele falharia nos últimos seis.

Você levanta a preocupação de que “O popd descomentado é exposto a outras consequências indesejáveis, .... i.e., que tal o caso se um arquivo (não um dir) estiver presente entre os dirs (no mesmo nível) sendo iterados por loop for ”. Bem,

  • Essa lógica é como dizer: "Se eu usar um sapato direito além do sapato esquerdo, que me dá mais uma coisa para apontar minha arma, por isso tenho maior probabilidade de me atirar com o pé direito. ” Isso não faz sentido. Fazendo pushd e não seguindo com popd (especialmente em um loop) é muito, muito mais errado do que usar apenas um sapato.
  • Como você está usando */ , você receberá apenas diretórios.
    • Mas Kusalananda está certo: você deve usar for d in */ em vez de for d in 'ls -d */'⁠ .
  • Melhor ainda, você poderia fazer algo como

    for d in *
     do
        …
        if [ -d "$d" ]
        then
            pushd "$d"
            for f in *.jp2
             do
                …
             done
            popd    
        fi
     done
    

    ou

    for d in *
     do
        …
        if pushd "$d" 2> /dev/null
        then
            for f in *.jp2
             do
                …
             done
            popd    
        fi
     done
    

    para que você não tente tratar um não diretório como um diretório.

por 06.10.2017 / 12:16