Gostaria de um script de shell bash (para meu sistema Debian 12) que aceitasse múltiplos caminhos como argumentos e, então, verificasse se um arquivo pode ser criado com sucesso em cada um deles. Então, o resultado deveria ser colocado no formato json.
O comando a ser executado deve ser:
./checkavailable.sh /the/first/path /the/second/path
(onde pode haver qualquer número de caminhos de entrada fornecidos, mas pelo menos um) e eu gostaria que a saída estivesse no seguinte formato:
[
{ "is_available": 0, "path": "/the/first/path/" },
{ "is_available": 1, "path": "/the/second/path/" }
]
Atualmente, consegui fazer isso com o seguinte script:
#!/bin/bash
# Check if first path is available
if touch $1/checkalivefile ; then
avail_path1=1
rm $1/checkalivefile
else
avail_path1=0
fi
# Check if second path is available
if touch $2/checkalivefile ; then
avail_path2=1
$2/checkalivefile
else
avail_path2=0
fi
echo "["
printf " { \"is_available\": "$avail_path1", \"path\": \"$1\" } "
printf ",\n"
printf " { \"is_available\": "$avail_path2", \"path\": \"$2\" } "
echo
echo "]"
mas é obviamente um pouco primitivo e é codificado para funcionar apenas com argumentos x2, e não é escalável para argumentos adicionais.
Eu poderia tentar adicionar um loop agora. No entanto, me deparei com este script, que parece fazer algo similar (para obter o uso do disco neste caso), mas usando awk em vez de um loop:
#!/bin/bash
echo "["
du -s -B1 "$@" | awk '{if (NR!=1) {printf ",\n"};printf " { \"dir_size_bytes\": "$1", \"path\": \""$2"\" }";}'
echo
echo "]"
Alguém pode mostrar como essa abordagem usando "awk" pode ser aplicada ao meu caso? Sou muito novo em scripts bash, então espero aprender alguma coisa.
JSON é uma escolha ruim de formato, pois, quando codificado em UTF-8 (como é frequentemente exigido hoje em dia, e muitas ferramentas não oferecem suporte a JSON codificado não UTF-8), suas strings não podem conter caminhos de arquivo arbitrários (que são sequências arbitrárias de bytes não NUL).
Mas se você estiver de acordo em produzir JSON não codificado em UTF-8, como muitas ferramentas no Linux
lsfd
fazem (mas que ferramentas como essajq
não conseguem processar), você pode fazer:Mas você também pode fazer um
perl
script:Observe que, em vez de tentar criar arquivos ali, o que é potencialmente destrutivo (e pode pelo menos atualizar o tempo de modificação desses diretórios), ele usa heurística (verifica se os caminhos identificam diretórios pesquisáveis (
-x
) ew
editáveisd
).Isso
->indent->space_after->indent_length(2)
é apenas para obter umajq
formatação bonita no estilo -. Você pode removê-lo para obter JSON compacto (como comjq -c
).Substitua
!!
porint
ou,0+
por exemplo, se você quiseris_available
que seja um número0
/1
em vez de um booleanofalse
/ .true
Seu script e o
df
script testam coisas diferentes. Um testa "posso escrever neste diretório" e o outro poderia testar "há espaço neste disco".Supondo que você queria o teste "posso escrever", seu script original está próximo, mas você precisa refatorar um pouco e fazer um loop na entrada.
O grande problema com um loop simples como esse é remover o "," final, então colocamos isso em uma linha própria e então excluímos a última linha do loop. O JSON não se importa onde a vírgula está, contanto que ela esteja lá.
Provavelmente
touch
também precisa ser jogado fora.Esta versão não foi testada...
Muitos shells derivados de Bourne têm primitivos para verificar esse tipo de coisa, tornando
touch
desnecessários os shells inferiores que têm umtest
utilitário semelhante a - com operadores-d
and :-w
Usando matriz associativa de
bash4+
.help test
para verificar permissões. Como o que a outra resposta postada sugeriu. Em vez detouch
erm
Poderia ser algo como:json
estrutura de dados usando o shell.Como os caminhos UNIX podem muito bem conter aspas duplas e outros caracteres que, quando interpolados diretamente, quebrariam um arquivo JSON, seria mais seguro deixar um processador JSON cuidar da tarefa.
O roteiro também poderia ser bastante simplificado.
Eu faria algo assim:
Se for garantido que os caminhos não contêm sequências UTF-8 inválidas; caso contrário, como Stéphane Chazelas observa, algum tipo de codificação é necessária para representar corretamente os caminhos usando JSON; veja a resposta de Stéphane Chazelas para um método que lida com caminhos que contêm sequências UTF-8 inválidas.
Para cada parâmetro
$p
, ele testará se o argumento não é um diretório gravável e pesquisável, de modo que$?
conterá0
se o diretório não é gravável e pesquisável /1
se o diretório não é gravável e pesquisável;Em seguida, ele alimentará um argumento nomeado
is_available
com um valor de$?
e um argumento nomeadopath
com um valor de$p
parajq
, que produzirá um objeto JSON (bem formado) contendo os dados;Por fim, ele alimentará o fluxo de objetos para
jq -s
redução em uma matriz.Observe que isso
is_available
deve ser representado como um booleano, caso contrário, o que estiver analisando o JSON pode ter que testar a igualdade numérica em vez da veracidade:Em vez de tocar, eu testaria para ver se o caminho é gravável
[[ -w "$p" ]]
. Para testar especificamente o diretório e gravável, então[[ -d "$p" && -w "$p" ]]
. Também recomendo jo para lidar com a criação de quaisquer objetos json. Isso torna tudo muito fácil