Em vez de usar mv
, apenas redirecione cat
. Por exemplo:
TMP=$(mktemp)
modifyfile "$original" "$TMP"
cat "$TMP" > "$original"
Isso sobrescreve $original
com o conteúdo de $TMP
, sem tocar em nada no nível do arquivo.
Eu tenho um comando que aceita um arquivo como um argumento, modifica o arquivo e grava-o no nome do arquivo especificado no segundo argumento. Vou chamar esse programa modifyfile
.
Eu queria que funcionasse "no lugar", então escrevi um script de shell (bash) que o modifica para um arquivo temporário e o move de volta:
TMP='mktemp'
modifyfile "$original" "$TMP"
mv -v "$TMP" "$original"
Isso tem o efeito colateral infeliz de destruir as permissões nesse arquivo. O arquivo é recriado com permissões padrão.
Existe uma maneira de dizer ao comando mv
para sobrescrever o destino sem alterar suas permissões? Ou, alternativamente, existe uma maneira de salvar o usuário, o grupo e as permissões do original e restaurá-los?
Existem duas estratégias para substituir um arquivo por uma nova versão:
Crie um arquivo temporário com a nova versão e mova-o para o lugar.
Substituir o arquivo antigo no lugar.
Se puder, use o método 1, mas primeiro replique os atributos do arquivo original com cp -p
. Isso replica os dados também, você não pode escapar disso com ferramentas básicas.
tmp=$(mktemp)
cp -p "$original" "$tmp"
modifyfile "$original" "$tmp"
mv -f "$tmp" "$original"
Se não for possível replicar os atributos do arquivo existente, por exemplo, porque você tem permissões de gravação, mas não o possui e deseja preservar o proprietário, somente o método 2 é possível. Para minimizar o risco de perda de dados:
tmp=$(mktemp)
backup="${original}~"
modifyfile "$original" "$tmp"
cp -p "$original" "$backup"
cp -f "$tmp" "$original"
Após nossa discussão sobre a primeira resposta, proponho uma resposta diferente:
TMP="$(mktemp "$original".XXXXXXXXXX)"
modifyfile "$original" "$TMP"
chmod --reference="$original" "$TMP"
chown --reference="$original" "$TMP"
mv -f "$TMP" "$original"
Observações:
$original
no modelo mktemp
para garantir que o arquivo temporário não seja colocado em /tmp
, mas na mesma pasta que $original
. Acredito que, se /tmp
estiver montado em um sistema de arquivos diferente, a operação não será mais atômica. mktemp
agora é citado no caso de conter espaço em branco. $()
em vez de '' porque eu considero isso mais limpo. ch{mod,own} --reference
são usados para transferir as permissões de $original
para $TMP
. Se alguém tiver ideias adicionais sobre quais metadados podem e devem ser transferidos, edite a minha publicação e adicione-a. Tags permissions bash files scripting