Encontrei muitas perguntas sobre como excluir apenas links simbólicos ou excluir links simbólicos com base em seu conteúdo, mas ninguém perguntou como fazer o que eu quero fazer.
Tome o seguinte exemplo
file-l -> ../file
file-l2 -> ../file
Desejo excluir file
, file-l
e file-l2
de uma só vez, sem conhecer a localização dos outros arquivos, preferencialmente especificando file
como argumento. (imagine que eu tenha mais de 100 links para o mesmo arquivo em lugares aleatórios em todo o sistema de arquivos). Primeiramente, eu preferiria um script de shell ou um programa interno, mas os programas externos também estão bem.
Depois que unlink
e rm
não forneceram a funcionalidade desejada, inicialmente tive a ideia de usar inodes
ou stat
ou algo assim, mas ...
$ stat test
File: ‘test’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 811h/2065d Inode: 27001032 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ braden) Gid: ( 1000/ braden)
Access: 2015-08-30 21:30:35.578786598 -0600
Modify: 2015-08-30 21:30:35.578786598 -0600
Change: 2015-08-30 21:30:35.578786598 -0600
Birth: -
$ stat test-l
File: ‘test-l’ -> ‘test’
Size: 4 Blocks: 0 IO Block: 4096 symbolic link
Device: 811h/2065d Inode: 27001033 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 1000/ braden) Gid: ( 1000/ braden)
Access: 2015-08-30 21:30:42.074786598 -0600
Modify: 2015-08-30 21:30:41.426786598 -0600
Change: 2015-08-30 21:30:41.426786598 -0600
Birth: -
Não só o link simbólico tem um inode único (isso é um dado), mas não parece haver nenhuma informação além do nome do arquivo que eu possa usar para concluir que "sim, este é um link simbólico para o arquivo I quer". Se eu usar o nome do arquivo, então, eu tenho que lidar com o regex-hell. Isso é algo que eu pessoalmente gostaria de evitar, pois, na prática, os nomes dos arquivos contêm caracteres como espaço, meta-caracteres ( ?![]{}.,
) e caracteres unicode.
Eu também gostaria de evitar coisas como awk, perl, hacks loucos que exploram bugs / falhas de design no bash 4.2.XX, e outras coisas estranhas que provavelmente não funcionariam corretamente (se forem) em uma nova instalação de, por exemplo, Arch Linux ou CentOS. Basicamente eu deveria ser capaz de rodar o dito comando / script fora da caixa em um sistema que não tenha awk, sed, perl, ruby e python, e execute o bash-4.1 como seu shell.
Se isso não for possível, prefiro pelo menos que o script / comando seja onipresente, como vi
, cat
, ls
, etc.
O mínimo dos meus requisitos é que a solução:
- pode excluir um arquivo e todos os seus links simbólicos apenas com o arquivo original como um argumento
- pode fazê-lo sem saber os nomes ou localizações dos referidos links simbólicos
- pode fazer isso em links simbólicos de nomes variados e locais variados
- funciona em uma instalação nova e mínima do Arch Linux (ou sistema mínimo semelhante)
- não é um código de golfe
- regexes razoáveis e fáceis de entender
É assim que tento projetar meus próprios scripts, por isso considero razoável. Mas, no entanto, espero que não seja muito exigente.
Obrigado.
Edit: Eu sinto que sou obrigado a mostrar o meu trabalho. Apenas solicitando um script me faz sentir como um idiota. Então, é isso que eu tenho:
get_lnk(){
gl_file=""
gl_orig_a=( $(ls -l "$gl_file") )
gl_orig="${gl_orig_a[-1]}"
}
for i in *; do
get_lnk "$i"
echo "file: $gl_file"
echo "links to: $gl_orig"
echo
done
# output:
file: file-l
links to: ../file
file: file-l2
links to: ../file
Isto imprime o nome do symlink e o nome do arquivo para o qual ele aponta. Isso é realmente o oposto do que estou tentando fazer, mas é razoavelmente útil (quando todos os links estão no mesmo lugar).