erros na expansão de parâmetros em nomes de arquivos com nomes negativos

2

Eu tenho alguns arquivos em um diretório:

$ ls *
-008.png  0052.png -002.jpg  0043.png  -005.png  0044.png ...

Eu gostaria de copiar os arquivos para um subdiretório subdir (sem sobrescrever os arquivos existentes) e renomear os arquivos adicionando um determinado número (digamos 10) ao nome do arquivo, para que os arquivos se tornem

$ ls subdir/*
0002.png  0062.png 0008.jpg  0053.png  0005.png  0054.png ...

Aqui está o meu comando bash

for filename in *
do
basename=${filename%.*}
extname=${filename#*.}
basename_new=$(printf %04d $((10#${basename}+10))); # 10#-008: value too great for base (error token is "003")
if [ ! -e subdir/"$basename_new".* ];  # [: subdir/.: binary operator expected
cp "$filename" "$basename_new"."$extname"
fi
done

Para alguns arquivos cujos nomes são números negativos, recebi erros, por exemplo, para -008.png (mas não para -002.png e não sei por que):

para a linha que atribui a basename_new :

10#-008: value too great for base (error token is "008")

para a linha com if :

# [: subdir/.: binary operator expected

Eu queria saber o que esses erros significam? Como posso resolvê-los?

Obrigado.

    
por Tim 22.09.2017 / 20:01

3 respostas

4

Uma palavra que começa com um traço é geralmente considerada como uma opção. Quando você executa ls * , o comando ls recebe ls 001.png -002.png ... e vê -002.png como um conjunto de opções que não entende. O mesmo para muitos comandos como cp , mv , ...

Solução # 1: prefixar os arquivos com o caminho deles. Funcionará em todos os casos.

ls ./*

Solução # 2: muitos comandos, especialmente no mundo GNU, aceitam um duplo traço como parâmetro, indicando que o que segue não são opções

ls -- *

No entanto, os traços iniciais não afetarão você for loop.

Quanto ao "valor muito grande para a base", é devido a -008 ser considerado como um número octal porque começa com um 0. No entanto, 8 não é um dígito octal válido. Uma solução rápida seria usar bc :

printf -v basename_new %04d "$(bc <<< "${basename} + 10")"

Você emite com if é causado por um basename_new vazio e desaparecerá com a correção acima.

    
por 22.09.2017 / 20:10
2

com zsh :

$ autoload zmv
$ zmv -n '((-|)<->).(png|jpg)' '${(l:4::0:)$(($1 + 10))}.$3'
mv -- -002.jpg 0008.jpg
mv -- 0043.png 0053.png
mv -- 0044.png 0054.png
mv -- 0052.png 0062.png
mv -- -005.png 0005.png
mv -- -008.png 0002.png

(remova o -n para realmente fazer isso).

  • (-|) glob: - ou "": um - opcional
  • <-> glob: qualquer sequência de dígitos decimais (como <x-y> mas sem limites).
  • ${(l:4::0:)param} : padding esquerdo (e truncamento) de comprimento 4 com zeros.
  • $(($1 + 10)) : os dados capturados pelo primeiro par de (...) no padrão, incrementados em 10 ( zsh não tem esse problema que números com 0s iniciais são tratados como octal; mesmo se você definir o octalzeroes opção, que não afeta zmv , que reverte para opções sane zsh enquanto é executado.
por 05.11.2018 / 22:53
0

10#-008 não fará -008 se tornar decimal. Eu acho que é porque 10# precisa estar na frente de dígitos ao invés de sinais.

    
por 05.11.2018 / 20:32