Encontrar diretórios excluindo o colchete final ')'

3

Estou tentando listar todos os diretórios de vídeos (não arquivos) que não terminam em um ano, por exemplo. (2015) e, mais especificamente, que não têm um ano listado, portanto, não terminem em um colchete de fechamento ) .

Como posso fazer o oposto do seguinte:

# List all files and directories end with '(2015)'
ls -ld *\(2015\)

# List all files and directories end with ')'
ls -ld *\)

Alguém pode ajudar a explicar como fazer isso?

    
por Paul Cee 17.02.2016 / 15:55

7 respostas

4

Tente isto:

ls -ld *[^\)]

[] - conjunto de caracteres nos quais estamos interessados

^ - negação (então incluímos um conjunto de caracteres que não queremos)

\) - escapado ')'

    
por 17.02.2016 / 16:11
2

No bash ou zsh:

for i in *; do [ -d "$i" ] && [[ ! "$i" =~ \)$ ]] && printf "%s\n" "$i"; done

Isso simplesmente fará o ciclo de todos os arquivos e diretórios no diretório atual e verificará se i) eles são um diretório ( [ -d "$i" ]) e ii). Seu nome não termina com ) ( [[ ! "$i" =~ \)$ ]] . items passando os dois testes serão impressos.

Isso pode lidar com nomes de arquivos arbitrários ( que ls não podem ).

    
por 17.02.2016 / 16:08
2

Método 1a:

ls -ld -- *[^\)]

(usando o padrão de expansão […] nome do caminho (curinga / glob): [abc] corresponde a a , b ou c ; [^abc] corresponde a qualquer coisa, exceto a , b ou c ; então [^\)] corresponde a qualquer coisa, exceto ) .)

Método 2a:

GLOBIGNORE="*)"
ls -ld -- *

Bastante auto-explicativo?

Ambos os métodos corresponderão aos arquivos e outros objetos que não são diretórios.

Atualizado com a sugestão de don_crissti, para encontrar somente diretórios:

Método 1b:

ls -ld -- *[^\)]/

Método 2b:

GLOBIGNORE="*)/"
ls -ld -- */

Observe que você deve incluir o / no valor GLOBIGNORE .

    
por 17.02.2016 / 16:13
2

Seu comando ls -ld *\(2015\) deve ser dividido em duas partes:

  • A globalização do nome de arquivo é feita pelo shell. Assim, diferentes shells podem funcionar de forma diferente.
  • O comando ls imprime uma linha longa -l para cada um dos nomes de arquivos listados pela expansão feita pelo shell. Evitando ir dentro dos diretórios com -d .

Shell

Em geral, isso funcionará com todos os shells para produzir todos os diretórios (com um trailing /) adicional:

echo */                           ### disregarding effects of '-' and '\'

E para produzir todos os diretórios que não correspondem a uma finalização ) :

echo !(*\))/
printf '%s ' !(*\))/ ### evite a interpretação de \ .
echo -E ^*\)/

Com o globbing estendido ativo para o bash e o zsh (o ksh o usa por padrão).

shopt -p extglob            ### for bash (on by default in interactive use).
setopt extendedglob         ### for zsh

Remover Trailing /

set -- */
printf '%s ' "${@%/}"

Ou para o bash e o ksh (por exemplo):

set -- !(*\))/
printf '%s ' "${@%/}"

O zsh oferece uma maneira mais simples de remover o \ .

[tag:zsh]'echo -E ^*\)(/)'

Sobre [! \)]

Observe que acima omiti (de propósito) o uso de [ ] .

O uso de [!\)] pode parecer equivalente (para um caractere):

echo !(*\))/
echo *[!\)]/

Mas os colchetes não funcionam para uma string. Isto é não equivalente:

echo !(*\(2015\))/
echo *[!\(2015\)]/

No entanto, deve-se notar que echo *[!\)]/ funciona para shells POSIX.

ls -ld -- *[!\)]/                               ### POSIXly.

Junte-se a ls e * /

Dependendo do shell, e se um / é um problema ou não.
As duas partes ls e shell juntas podem ser:

ls -ld -- !(*\(2015\))/              ### An example for bash and GNU ls.

Alternativas

O comando (GNU) ls em si inclui uma maneira de evitar padrões:

ls -l --ignore='*)'

Bash oferece GLOBIGNORE:

GLOBIGNORE='*)/'; echo */

Talvez find ?

find . -maxdepth 1 ! -name . -prune -type d ! -name '*2015)'

Mas encontrar parece ser um exagero para mim por esta simples necessidade.

    
por 18.02.2016 / 10:38
1

POSIXly:

find . ! -name . -prune -type d ! -name '*)'

com zsh :

print -rl -- *[^\)](/)

Outros shells parecidos com Bourne não têm capacidade de filtrar o resultado de globbing. Você pode usar:

printf '%s\n' *[!\)]/

para corresponder somente aos diretórios. Mas isso adicionará uma barra ao seu resultado de expansão. Com o diretório foo , você receberá foo/ .

    
por 17.02.2016 / 16:04
0

Usando o bash, você pode usar GLOBIGNORE :

$ ls -d1 *
excludeme(2015)
excludmetoo(2016)
somedir

$ GLOBIGNORE='*)'
$ ls -d1 *
somedir

GLOBIGNORE:

A colon-separated list of patterns defining the set of filenames to be ignored by filename expansion. If a filename matched by a filename expansion pattern also matches one of the patterns in GLOBIGNORE, it is removed from the list of matches.

    
por 17.02.2016 / 16:08
0

Acho que encontrar é bastante apropriado para isso

find . -type d ! -regex '^.*)' -ls

-regex '^. *)' combina todos os nomes que terminam com um suporte! inverte isso, -tipo d opção é para dirs, -ls (opcionalmente) faz com que a saída pareça ls-like

    
por 17.02.2016 / 16:45

Tags