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
.