Como listar nomes de arquivos que contenham espaços e caracteres especiais sem usar find

2

Estou escrevendo um script que requer que eu forneça uma lista de arquivos em meu diretório, cujos nomes de arquivos contêm espaços, *,?, $,%, etc. Como posso fazer isso, tenho visto várias postagens, mas não consegui encontrar nada que funcione para mim. É possível conseguir isso usando grep?

    
por KLMM 25.09.2015 / 17:50

4 respostas

1

grep -E deve fazer o que você precisa. Observe que alguns caracteres precisam ser escapados com uma barra invertida, portanto, se você adicionar mais e os resultados não forem os esperados, escape e tente novamente. Observe o | é um or ...

$ ls | grep -E '\s|\*|\?|\$|%'
all this.txt
all?this.txt
all*this.txt
all%this.txt
all th*s.txt
all$.txt
    
por 25.09.2015 / 18:04
3
printf '<%s>\n' *[[:space:]*?$%]*

Não reportará arquivos ocultos. Se [[:space:]] corresponderá a caracteres de espaçamento de bytes múltiplos (como " " ( EM QUAD ) em UTF-8) depende do seu shell (alguns como dash ainda não são compatíveis com caracteres multi-byte)

Exemplo:

$ touch sane 'a%b' $'with\nnewline' $'with space' $'with em-quad'
$ printf '<%s>\n' *[[:space:]*?$%]*
<a%b>
<with em-quad>
<with
newline>
<with space>
    
por 25.09.2015 / 18:33
2

Uma lista segura de arquivos é produzida com um * sem aspas, sem ser usado:

$ echo *

Vamos ter alguns arquivos para testar:

$ mkdir test-dir; cd test-dir
$ touch clean normal_file 'a%b' 'has two spaces' '*' 'a*b' '?' 'a?b'
$ touch '$' 'a$b' '%' 'a%b' $'new\nline' $'em\u2001quad' 'normal_file'

O comando echo * produzirá, com os arquivos acima:

? $ * % a?b a$b a*b a%b clean em quad has two spaces new
line normal_file

Uma lista separada por espaço, que, sim, tem duas linhas, pois há um arquivo com uma nova linha em seu nome.

Uma maneira mais fácil de ver os arquivos é citar o nome deles com printf '%q' e adicionar uma nova linha, como printf '%q\n' , recebemos uma lista limpa de arquivos:

$ printf '%q\n' *
\?
\$
\*
%
a\?b
a\$b
a\*b
a%b
clean
$'em201quad'
has\ two\ spaces
$'new\nline'
normal_file

Claro, você precisa selecionar alguns arquivos, não todos, como com o plain *.
Então, criamos um padrão de todos os caracteres para corresponder: ?$*% .
No entanto, a maioria desses caracteres é "especial" e precisa ser citada quando aparece em alguns pedidos. Especificamente, se * ou ? seguir $ , eles serão expandidos pelo shell, o que poderia criar problemas.
É imperativo citar o $ .
Então, uma maneira fácil de obter todos os outros caracteres citados é usar printf '%q' ?\$*% . Isso produzirá: \?\$\*% . Se a barra invertida não for estritamente necessária, ela não produzirá nenhum efeito negativo, o caractere de escape ainda funcionará.
Para essa lista, precisamos adicionar alguns caracteres em branco. Mas a inclusão da nova linha se torna um problema sério. A maneira mais fácil de lidar com a nova linha dentro de uma classe de caracteres é usar [[:space:]] , que incluirá nova linha, espaço, tabulação e alguns outros caracteres de espaço como em-traço.

Portanto, o comando se torna:

$ printf '%q\n' *[\?\$\*%[:space:]]*
\?
\$
\*
%
a\?b
a\$b
a\*b
a%b
$'em201quad'
has\ two\ spaces
$'new\nline'

Observe que os nomes dos arquivos clean e normal_file não foram listados, conforme necessário.

    
por 26.09.2015 / 00:02
0

Isso é muito simples e já funcionou com a Bourne Shell de 1979:

for i in *
do
    case "$i" in
        *\ *) echo blank $i;;
        *\?*) echo qmark $i;;
    esac
done

em uma linha:

for i in *; do
    case $i in
        *\ *|*\?*|*\**|*\$*|*%* ) echo "Special character $i"; ;;
        * ) echo "normal file $i"; ;;
    esac
done

Adicione mais casos, se quiser ...

    
por 25.09.2015 / 23:13