Como faço para retornar o primeiro resultado correspondente em cada pasta com o comando find no tcsh?

1

Eu quero encontrar todos os arquivos .mb em várias pastas grandes, mas só quero retornar um arquivo de cada pasta se houver muitos arquivos que correspondam ao meu critério de pesquisa.

estrutura de pastas

..
--abc
    |_scenes
    |    |__  file1.mb
    |    |__  file2.mb
    |...
--def
    |_scenes
    |    |__  file3.mb
    |    |__  file4.mb
    |...

se eu fizer

find /net/*/scenes -maxdepth 1 -type f -size +200M

Retorna todos

file1.mb
file2.mb
file3.mb
file4.mb

Como posso retornar somente file1.mb e file3.mb ?

    
por Shuman 15.06.2018 / 18:34

3 respostas

1
Solução

find + awk :

find /net/*/scenes -maxdepth 1 -type f -name "*.mb" \
| awk -F'/' '{ fn = $NF; $NF = "" }!a[$0]++{ print $0 fn }' OFS='/'
  • -F'/' e OFS='/' - representam o separador de campos de entrada e saída
  • fn = $NF - armazenando o último valor do campo (ou seja, um nome de arquivo) na variável fn
  • !a[$0]++{ print $0 fn } - na primeira ocorrência do caminho de diretório exclusivo (apresentado por $0 ) imprime a linha (todo o caminho do arquivo)

Ou usando o GNU coreutils pipeline:

find /net/*/scenes -maxdepth 1 -type f -name "*.mb" -printf "%H %p\n" \
| sort -k1,1 -u | cut -d' ' -f2
    
por 15.06.2018 / 18:51
0

Sua nova edição especifica que você está usando tcsh - inicialmente presumi que você estava usando bash . Você poderia chamar find de dentro de uma invocação de find -exec e canalizar cada invocação interna de find para head para extrair o primeiro resultado, por exemplo,

find /net/* -maxdepth 1 -exec tcsh -c "find {} -maxdepth 1 -type f -name '*.mb' -size +200M | head -1" \;

Aqui está um pequeno exemplo de demonstração:

# Create the directory structure
mkdir -p test/abc/scenes
mkdir -p test/def/scenes

# Create example data files
dd if=/dev/zero of=abc/scenes/file1.mb bs=201M count=1
dd if=/dev/zero of=abc/scenes/file2.mb bs=201M count=1
dd if=/dev/zero of=def/scenes/file3.mb bs=201M count=1
dd if=/dev/zero of=def/scenes/file4.mb bs=201M count=1

# Execute the find command
find ./* -maxdepth 1 -exec tcsh -c "find {} -maxdepth 1 -type f -name '*.mb' -size +200M | head -1" \;

Isso produz a seguinte saída:

./abc/scenes/file1.mb
./def/scenes/file3.mb

Originalmente, a pergunta não especificou tcsh . Em bash , você poderia chamar find de dentro de um loop e canalizar cada find invocação para head para extrair o primeiro resultado, por exemplo,

for directory in /net/*/scenes; do
    find "${directory}" -maxdepth 1 -type f -name '*.mb' -size +200M | head -1;
done

Aqui está um pequeno exemplo de demonstração:

# Create the directory structure
mkdir -p test/abc/scenes
mkdir -p test/def/scenes

# Create example data files
dd if=/dev/zero of=abc/scenes/file1.mb bs=201M count=1
dd if=/dev/zero of=abc/scenes/file2.mb bs=201M count=1
dd if=/dev/zero of=def/scenes/file3.mb bs=201M count=1
dd if=/dev/zero of=def/scenes/file4.mb bs=201M count=1

# Execute the find command
for directory in ./*/scenes; do
    find "${directory}" -maxdepth 1 -type f -name '*.mb' -size +200M | head -1;
done

Isso produz a seguinte saída:

./abc/scenes/file1.mb
./def/scenes/file3.mb
    
por 15.06.2018 / 18:47
0

Usando 2 comandos de busca primeiro para encontrar diretórios, então pesquise em cada um deles:

while read dir; do find "$dir" -name "*.mb" -maxdepth 1 | head -1 ; done << EOF
$(find /net/*/scenes -type d)
EOF
    
por 15.06.2018 / 19:05