Encontre nomes de arquivos que não contenham uma sequência especificada

19

Eu gostaria de executar o oposto de:

find . -name "*2013*"

Encontre todos os arquivos no diretório atual que não contenham a cadeia "2013" em seus nomes. Como eu posso fazer isso?

user1058398
fonte

Respostas:

28

Simplesmente:

find . ! -name '*2013*'

Adicione a ! -type dpara excluir também os arquivos do diretório de tipos (como .ele próprio) ou -type fpara incluir apenas arquivos regulares , excluindo todos os outros tipos de arquivos (diretórios, fifos, links simbólicos, dispositivos, soquetes ...).

Cuidado, porém, que *corresponda a uma sequência de 0 ou mais caracteres . Portanto, ele poderia relatar nomes de arquivos que contenham 2013se isso 2013foi precedido ou seguido por algo que não pode ser totalmente decodificado como caracteres válidos no código de idioma atual.

Isso pode acontecer se você estiver em uma localidade em que os caracteres possam ser codificados em mais de um byte (como em UTF-8) para nomes de arquivos codificados em uma codificação diferente. Por exemplo, em um código de idioma UTF-8, ele reportaria um Stéphane2013arquivo se esse étivesse sido codificado no conjunto de caracteres iso8859-15 (como o byte 0xe9).

O melhor seria garantir que os nomes dos arquivos sejam codificados no conjunto de caracteres da localidade, mas se você não puder garantir isso, uma solução alternativa será executar findna localidade C:

LC_ALL=C find . ! -name '*2013*'
Stéphane Chazelas
fonte
4

Os padrões de nome de arquivo Ksh são suficientes:

# files with 2013
ls -d -- *2013*

# files without 2013
ls -d -- !(*2013*)

Referência

Se o seu shell for bash, você precisará executar shopt -s extglobantes de poder usar esse padrão (você pode colocá-lo no seu .bashrc). Se o seu shell for zsh, você precisará executar setopt ksh_glob(você pode colocá-lo no seu .zshrc). O Zsh também oferece ls -d -- ^*2013*, o que requer uma preliminar setopt extended_glob.

Dependendo do que você está fazendo com esses nomes de arquivos, lspode não ser o comando certo a ser usado. Para armazená-los em uma matriz

filenames=( !(*2013*) )
for f in "${filenames[@]}"; do ...; done
Glenn Jackman
fonte
4
Isso não ocorre em subdiretórios e, no entanto, ignora os arquivos de ponto (e lsretornará uma mensagem de erro se o padrão não corresponder a nenhum arquivo). Observe também que kshirá classificar a lista.
Stéphane Chazelas
-1

Encontre todos os arquivos no diretório atual que não contém uma determinada string, aqui "2013":

find . ! -name "*2013*" -type f
user7194913
fonte
2
É basicamente a mesma coisa que unix.stackexchange.com/a/102614/117549 de 3 anos atrás, exceto que você adicionou "-f", o que torna a resposta pior.
Jeff Schaller