Como garantir que um nome de arquivo de 3 caracteres contenha um de 2 caracteres?

2

Portanto, tenho que pesquisar em um diretório por arquivos de 3 caracteres. Isso é fácil, o problema é que pelo menos 1 dos 3 caracteres precisa ser um "B" ou um "y". Eu sei que [By] se certificaria de que o caractere é um B ou um y, mas simplesmente fazer [By] [By] [By] não seria suficiente, já que não é um requisito que todos os 3 caracteres sejam B ou y; apenas 1 deles tem que ser. Por favor ajude.

    
por John Stacen 27.09.2013 / 09:29

3 respostas

2

Você pode fazer uma correspondência de padrões em um loop.

for file in ./???; do
    [[ -e $file && $file = *[By]* ]] || continue
    printf 'Do stuff with <%s>\n' "$file"
done

Ou você pode ativar os globs estendidos executando shopt -s extglob . Então você pode usar algo como @([By]??|?[By]?|??[By])

shopt -s extglob
for file in ./@([By]??|?[By]?|??[By]); do
    [[ -e $file ]] || continue
    printf 'Do stuff with <%s>\n' "$file"
done

Ou será mais eficiente do que envolver grep .

Se você estiver criando scripts para o POSIX sh, poderá fazer algo assim:

for file in ./???; do
    [ -e "$file" ] || continue
    case $file in 
        *[By]*) : ;;
        *) continue;;
    esac
    printf 'Do something with <%s>\n' "$file"    
done

Por último, você pode usar três globs, embora isso imite os arquivos em uma ordem diferente e você corre o risco de repetir o mesmo arquivo várias vezes.

for file in ./[By]?? ./?[By]? ./??[By]; do
    [ -e "$file" ] || continue
    printf 'Do something with <%s>\n' "$file"    
done
    
por geirha 29.09.2013 / 12:00
2
printf '%s\n' ??? | grep '[By]'

O printf '%s\n' imprime cada argumento passado para ele, um por linha; o ??? é um glob que se expande para cada nome de arquivo de três caracteres no diretório de trabalho. Isso é canalizado para o grep , que imprime somente os nomes de arquivo que contêm o padrão que você especificou.

A propósito, eu me encontrei usando printf '%s\n' tanto que coloquei o seguinte em ~/.bashrc para facilitar a digitação:

alias necho='printf "%s\n"'  ##  newline-echo

Na maior parte do tempo, tudo ficará bem: ele quebrará em nomes de arquivos contendo novas linhas, mas na verdade são raros (eu só os vi quando os fiz especificamente para testar meus scripts). Provavelmente é possível criar uma solução pura e simples usando o extglob , mas você também pode usar find para contornar esse problema. questão:

find . -name '???' -a -name '*[By]*'

Isso funcionará de forma recursiva por padrão; se você não quiser, use -maxdepth 1 .

find . -maxdepth 1 -name '???' -a -name '*[By]*'
    
por evilsoup 27.09.2013 / 13:02
2

Experimente este (s) comando (s):

cd /path/to/directory
ls | while read file; do if [ ${#file} -eq 3 ]; then echo $file; fi; done | grep '[By]'

ou:

for file in ???; do echo $file; done | grep '[By]'

ou uma variante sem loop:

ls | grep -ow '\w\{3\}' | grep '[By]'

ls listará todos os arquivos do diretório atual, em seguida, selecionamos apenas os nomes de arquivos com exatamente 3 caracteres e, finalmente, usando grep , selecionamos apenas os nomes de arquivos que contêm B ou y .

    
por Radu Rădeanu 27.09.2013 / 11:08