Eu tenho o próximo problema:
O diretório Example1
possui três arquivos Example1
: Things
e Pictures
.
O diretório Example2
possui três arquivos Example2
: Example3
e Pictures
.
Preciso de uma lista mostrando apenas os arquivos que correspondem ao nome do diretório, isto é: Example1
e Example2
. Eu tentei com diff, find, localizar e ls... mas não consegui nada.
Responder1
Você pode combinar facilmente nomes de arquivos que tenham o mesmo nome do diretório que os contém com uma regex usando uma referência anterior. Esses são nomes de arquivos no formato what/ever/something/something
em que as duas something
partes são idênticas e não contêm barras. Na sintaxe BRE regex, [^/]*
corresponde a qualquer string que não contenha uma barra, \(/[^/]*\)
corresponde a uma barra seguida por qualquer número de caracteres não-barra e torna tudo um grupo, e \1
corresponde ao mesmo texto que corresponde ao primeiro grupo, portanto \(/[^/]*\)\1
corresponde a dois segmentos de caminho com o mesmo nome. Adicione .*
no início para corresponder aos componentes do diretório anterior.
Com GNU find, FreeBSD find, macOS find ou qualquer outro find
que suporte -regex
:
find . -regex '.*\(/[^/]*\)\1'
Responder2
Como geralmente há menos diretórios do que arquivos, vamos procurar todos os diretórios e testar se eles contêm o nome de arquivo necessário.
find . -type d -exec sh -c '
for dirpath do
filepath="$dirpath/${dirpath##*/}"
[ -f "$filepath" ] && printf "%s\n" "$filepath"
done' sh {} +
Isso imprimiria os nomes de caminho de todos os arquivos regulares (e links simbólicos para arquivos regulares) localizados em um diretório com o mesmo nome do arquivo.
O teste é feito em um script curto em linha sh -c
que obterá vários nomes de caminhos de diretório como argumentos. Ele itera sobre cada nome de caminho de diretório e constrói um nome de caminho de arquivo com o nome que estamos procurando. O ${dirpath##*/}
no código pode ser substituído por $(basename "$dirpath")
.
Para o exemplo de estrutura de diretório fornecido, isso resultaria
./Example1/Example1
./Example2/Example2
Para apenas testarqualquer nome, não apenas arquivos normais, altere o -f
teste para um -e
teste.
Responder3
Usar find -exec
:
find . -type f \
-exec sh -c '[ "$(basename "$1")" = "$(basename "$(dirname "$1")")" ]' find-sh {} \; \
-print
O -print
só será executado quando o resultado do [ ... ]
interior do -exec sh -c '...'
for verdadeiro.
Saída:
./Example1/Example1
./Example2/Example2