Para evitar problemas com espaço em branco, find e IFS magic (nomes de arquivos podem realmente conter novas linhas também, então IFS=$'\n' não é um marcador de prata), pode-se usar globs e arrays.
#!/bin/bash
search_dir=${1:-.}
shopt -s globstar dotglob
for svn_dir in "$search_dir"/**/.svn/; do
base_dir=${svn_dir%/.svn/}
base_dir_contents=("$base_dir"/*)
if [ ${#base_dir_contents[@]} -eq 1 ]; then
printf 'The directory "%s" only contains ".svn/".\n' "$base_dir"
fi
done
- O script usa um argumento de caminho opcional ou usa o caminho atual como padrão, se ausente.
-
globstar ativa o diretório percorrendo ** construct.
-
dotglob inclui arquivos ocultos em globos de asterisco.
- O
for glob deve ser seguro contra qualquer caractere de nome de diretório problemático. Globs sempre expandirão com segurança no Bash, o que não é o caso de ls , find , etc. A barra à direita garante que apenas correspondamos pastas chamadas .svn e não arquivos regulares (um caso de canto real, no entanto).
- Os nomes dos arquivos contidos na pasta com o diretório
.svn correspondente são colocados em uma matriz. Se o número de itens nessa matriz for 1 (ou seja, a pasta .svn que nós conhecemos por construção *), então é isso que estamos procurando.
Ele usa somente Bash built-ins e, portanto, deve ser mais rápido do que emitir garfos de sistema extras para find , mas a diferença provavelmente não é perceptível, e a E / S será o principal gargalo de qualquer maneira.
*: Sidenote menor (aplica-se também a outras soluções): existe uma possível condição de corrida se houver, por exemplo. somente o arquivo .svn e o foo em um diretório, e o diretório .svn é removido entre o for e o glob da matriz, o que resultaria em foo sendo removido também. No entanto, se alguém com intenção mal-intencionada tiver o privilégio de remover arquivos no sistema de arquivos, o jogo provavelmente já estará perdido e será mais fácil removê-los diretamente do que através de ataques de cronometragem.
Outra menção rápida é que as outras respostas devem citar as expansões *.svn* . Caso contrário, o comando find falhará se a pasta atual contiver um arquivo que corresponda a esse glob:
$ mkdir foo && cd foo
$ mkdir -p test1/.svn test2
$ find -type d ! -path *.svn*
.
./test1
./test2
$ touch foo.svnbar
$ find -type d ! -path *.svn*
.
./test1
./test1/.svn
./test2
$ find -type d ! -path "*.svn*"
.
./test1
./test2
Sem aspas, *.svn* será expandido prematuramente pelo shell para foo.svnbar .