Como trabalho com “encontrar” strings e caracteres especiais?

3

Eu estou tentando escrever algum script de shell bash (pela primeira vez) para executar algumas ações sequenciais (algumas cópias, criptografia, upload e verificações lógicas simples) e estou lutando para trabalhar com as seqüências de caracteres find está retornando como eles têm caracteres especiais /\*)'(" e espaços.

Eu tenho visto sugestões para corrigir isso usando printf %q , mas não consegui descobrir a sintaxe correta do bash.

Aqui está um trecho de como estou tentando alterar as strings:

#!/bin/sh

find "/upload" -type f |
    while read -r path; do
        fixedpath=printf %q "$path"
        fixedpath=printf '%q' "$path"
        fixedpath=printf '%q' $path
        fixedpath=printf "%q" "$path"
        fixedpath="printf %q $path"
        fixedpath="printf '%q' $path"
        fixedpath=$(printf '%q' $path)
        echo $path >> list.txt
        echo $fixedpath >> list.txt
    done
exit 0

Eu poderia pensar em outras 6-12 maneiras de escrever a função printf também, mas eu acho que você entendeu, qual eu preciso ter um caminho válido retornado que eu possa usar para passar como um argumento para outros comandos?

Estou trabalhando no Ubuntu 16.

    
por user267461 25.12.2017 / 16:44

3 respostas

3

Não analise a saída de find , especialmente se você estiver esperando por nomes estranhos e maravilhosos.

Em vez disso, execute os comandos necessários para executar -exec ou incorpore um script no comando find :

find /upload -type f -exec sh -c '
    for pathname do
        printf "Would do something with \"%s\" here...\n" "$pathname"
    done' sh {} +

Obviamente, você também pode colocar o script incorporado em seu próprio arquivo:

#!/bin/sh

for pathname do
    printf 'Would do something with "%s" here...\n' "$pathname"
done

E então ...

find /upload -type f -exec /path/to/script.sh {} +

Mais leituras sobre este assunto:

por 05.05.2018 / 21:51
0

Note que usar #!/bin/sh limitará (provavelmente) as especificações POSIX, não bash . Já que você mencionou bash você deve mudar o shebang para #!/bin/bash .

Veja esta página , particularmente a seção "Outros exemplos". Meu método preferido, se você precisar usar find , é:

#!/bin/bash

while IFS= read -r -d '' f; do
   echo "$f"
   # Other actions on "$f" here
done < <(find /upload -type f -print0)

exit

Isso manipulará caracteres especiais com segurança usando um delimitador nulo.

Como alternativa, é mais simples usar algumas opções bash shell e um for loop:

shopt -s nullglob globstar

for f in /upload/**; do
   [[ -f $f ]] || continue
   echo "$f"
   # Other actions on "$f" here
done

Isso irá encontrar recursivamente arquivos regulares em /upload . Não deixe de citar "$f" nos dois métodos.

por 28.12.2017 / 19:52
0

O script falha (expande os asteriscos * ) quando estas linhas são executadas:

echo $path
echo $fixedpath

Exemplo:

$ path='test *'
$ echo "$path"
test *

$ echo $path
test file 1 file2 A longer file in this directory Some_Other_file ......

Solução? : Cite suas expansões de var.

Dito isto, a única tarefa que pode funcionar é (também citar):

fixedpath=$(printf '%q' "$path")
echo "$path" >> list.txt
echo "$fixedpath" >> list.txt

Mas a leitura da saída do find é uma má ideia que pode falhar de formas semelhantes, sem citar variáveis. Leia as outras respostas para essa parte, elas são boas.

    
por 20.07.2018 / 01:37