Seu script é codificado de maneira perigosa.
Primeiro, suponho que você esteja usando o shell Bash desde que você o marcou '/ bash' e '/ for'.
Em minha resposta, citarei este ótimo Guia Bash , que é provavelmente a melhor fonte para aprender Bash por aí.
1) Nunca use uma Substituição de Comando , do tipo sem aspas. Há um grande problema aqui: usar uma expansão sem aspas para dividir a saída em argumentos.
Especificamente, esse $(find $DIRWORK -type d -name work)
e $(find $DIR -type f)
passarão por Divisão de palavras , portanto, se find
encontrar um arquivo com espaços em seu nome, ou seja, "nome do arquivo", o resultado da divisão de palavras do Bash passará 2 argumentos para o comando for
para iterar, ou seja, um para "arquivo" e um para "nome". Nesse caso, você espera ter um "arquivo: Nenhum arquivo ou diretório" e "nome: Nenhum arquivo ou diretório", em vez de potencialmente causar danos a eles, se eles realmente existirem.
2) Por convenção, variáveis de ambiente (PATH, EDITOR, SHELL, ...) e variáveis de shell internas (BASH_VERSION, RANDOM, ...) são totalmente capitalizadas. Todos os outros nomes de variáveis devem estar em minúsculas. Como os nomes das variáveis fazem distinção entre maiúsculas e minúsculas, essa convenção evita a sobreposição acidental de variáveis ambientais e internas.
Seu diretório $ DIRWORK quebra essa convenção, e ela também não é citada, portanto, se deixarmos que DIRWORK='/path/to/dir1 /path/to/dir2'
, find
procure em dois diretórios diferentes quando $ DIRWORK estiver sem aspas. O assunto de usar aspas é muito importante no Bash, então você deve "Dobrar aspas" a cada expansão, bem como qualquer coisa que possa conter um caractere especial, por exemplo "$ var", "$ @", "$ {array [@]}", "$ (comando)". Bash trata tudo dentro de 'aspas simples' como literal. Aprenda a diferença entre "e" e ". Veja Citações , Argumentos e você também pode querer dar uma olhada neste link: link
Esta é uma versão mais segura do seu script, que eu recomendo que você use em vez disso:
my_home="/root/mydir"
my_dir="$my_home/var"
dir_work="$my_home/Local"
while IFS= read -r -d '' f; do
# I'm guessing that you also want to ignore stderr;
# this is where the 2>&1 came from.
if lsof -n "$f" | grep '[a-z]' > /dev/null 2>&1; then
echo "hey, I'm safer now!"
fi
done < <(find "$dir_work" -type f -print0)
while IFS= read -r -d '' f; do
echo "2"
done < <(find "$dir_work" -type d -name 'work' -print0)
Como você pode ver, a variável IFS
está configurada para ser vazia, evitando que read
corte os espaços iniciais e finais de uma linha. O comando read
usa uma string vazia ( -d ''
) como um delimitador para ler até atingir \ 0.
find
precisa ser modificado de acordo, portanto, usa a opção -print0
para delimitar seus dados com um \ 0 em vez de uma nova linha - que, de maneira surpreendente e maliciosa, pode fazer parte de um nome de arquivo. Dividir esse arquivo por \ n em duas partes quebrará nosso código.
Você pode querer ler sobre Substituição de processos se não entender meu script completamente.
A resposta anterior, que afirmou que find ... | while read name; do ...; done
deve ser usada para ler a saída find
s, também pode ser ruim.
O loop while
acima é executado em um novo subshell com sua própria cópia das variáveis copiadas do pai. Esta cópia é usada para o que você quiser. Quando o loop while
for concluído, a cópia da sub-camada será descartada e as variáveis originais do pai não serão alteradas.
Se você pretende modificar algumas variáveis dentro desse while
loop e usá-las posteriormente no pai, considere usar o script mais seguro acima, o que evitará a perda de dados.