Corrija o script bash esperando entrada de caminho com / no final quebrando quando o caminho não terminar com /

4

Eu tenho este código:

for file in "$@"*png; do
  echo "$file"
done

Funciona apenas se você fornecer um caminho que termine com / like /root/ .

Qual seria a maneira correta de adicionar / à entrada do caminho, em situações como essa, sem quebrar meu script?

Se você der uma entrada de caminho sem / no final, isso será feito:

File: /root*png

Se eu modificá-lo como for file in "$@"/*png; do e entrada /root/test/ , ele funciona, mas o resultado parece feio:

File: /root/test//sample2.png
    
por Freedo 07.01.2018 / 05:06

3 respostas

7

ilkkachu apontou uma grande falha na minha resposta e corrigiu-a na dele, então, por favor, dê-lhe o crédito que ele merece. Eu criei outra solução:

#!/bin/bash

for dir in "$@"; do
        find "$dir" -type f -name '*png' -exec readlink -f {}  \;
done

Exemplo :

$ ll
total 6
-rwxr-xr-x 1 root root 104 Jan  7 14:03 script.sh*
drwxr-xr-x 2 root root   3 Jan  7 04:21 test1/
drwxr-xr-x 2 root root   3 Jan  7 04:21 test2/
drwxr-xr-x 2 root root   3 Jan  7 04:21 test3/

$ for n in {1..3}; do ll "test$n"; done
total 1
-rw-r--r-- 1 root root 0 Jan  7 04:21 testfile.png
total 1
-rw-r--r-- 1 root root 0 Jan  7 04:21 testfile.png
total 1
-rw-r--r-- 1 root root 0 Jan  7 04:21 testfile.png

$ ./script.sh test1 test2/ test3
/root/temp/test1/testfile.png
/root/temp/test2/testfile.png
/root/temp/test3/testfile.png

Solução original :

for file in "${@%/}/"*png; do
  echo "$file"
done

O $ {@% /} irá aparar / desativar o fim do seu parâmetro e depois o / fora irá adicioná-lo de volta - ou adicioná-lo a qualquer parâmetro que não tenha um.

    
por 07.01.2018 / 05:15
3

Usar $@ com o glob assim parece um pouco estranho. Se você espera que seja capaz de processar vários argumentos, bem, não vai funcionar. As strings que envolvem $@ são anexadas apenas ao primeiro e ao item da lista.

$ mkdir a b; touch a/a.png b/b.png
$ set -- a b 
$ echo x"$@"x
xa bx
$ echo "$@/"*.png
a b/b.png

Portanto, para lidar com vários argumentos, você precisará executar o loop "$@" separadamente:

for arg in "$@"; do
    for file in "${arg%/}"/*.png; do
         echo "$file"
    done 
done

Em outro caso, você poderia usar a expansão de substituição de string ${//} (no Bash ou zsh) para adicionar um sufixo a cada parâmetro posicional, mas é muito difícil fazer isso funcionar com um glob.

    
por 07.01.2018 / 12:30
0

Você também pode usar o tr.

Sempre adicione / no final e ...

file='/root/test//sample2.png';echo "$file" | tr -s '/'
    
por 09.01.2018 / 08:30

Tags