Como lidar com caracteres como “:” ou “?” que fazem nomes de arquivos inválidos?

4

Eu apenas tentei mover um diretório contendo arquivos de música com thunar 4.10 Ele reclamou que um nome de arquivo era inválido.

Descobrimos que um nome de arquivo (título da música) continha um ponto de interrogação. Suspeitei que isso era um problema, removi o ponto de interrogação e copiei o arquivo. Adicionando o "?" de volta não foi possível. Eu também tentei com rename na linha de comando, mas isso não funcionou. (não sei o que o thunar usa sob o capô, então esse teste pode ser discutível)

Agora, se um ponto de interrogação invalida o nome do arquivo, como esse arquivo pode ser criado? Eu criei os arquivos com SoundJuicer de um CD recém-obtido. Consegui jogar o arquivo (com "?" No nome) em vários jogadores.

O que está acontecendo aqui? Eu posso ter "?" em nome ou não? Por que o gerenciador de arquivos não consegue lidar com esses arquivos enquanto outros aplicativos parecem estar ok?

Atualização: A próxima música tem um ":" nela. O mesmo problema que com o "?".

These are not invalid characters to Unix; typically only the NUL character and the / character are invalid filenames (the / being the directory separator).

Isso foi o que minha intuição também me disse, porque eu nunca tive nenhum problema com nomes de arquivos no Linux e pude jogar praticamente tudo de bom e funcionou bem. Isso é o que motivou a questão aqui. Eu nunca encontrei nomes de arquivos inválidos antes.

Were you trying to move the files to a USB stick? If so, is that stick formatted as FAT32 or as a native Linux filesystem?

O alvo é de fato um pendrive que eu comprei hoje. Eu abri gparted e está formatado como FAT32.

Eu não tenho certeza, mas isso é uma coisa do Windows, certo? E o Windows tem um monte de caracteres que ele não suporta, incluindo ? e : . Estou certo?

    
por null 01.08.2016 / 19:28

4 respostas

7

Esses caracteres ? e : não são válidos em um sistema de arquivos FAT32, então se é onde você precisa copiar seus arquivos, você precisará renomeá-los.

Na linha de comando, você pode usar ferramentas de linha de comando como rename (às vezes conhecido como prename ) para substituir esses caracteres por _ ou até mesmo para removê-los:

rename 's/[?<>\:*|\"]/_/g'    # Change invalid characters to _
rename 's/[?<>\:*|\"]//g'     # Remove invalid characters

Não estou familiarizado com thunar , portanto, não sei se existe uma maneira de realizar essa operação de substituição / substituição diretamente.

Acabei de encontrar cópia do Linux para o sistema de arquivos fat32: inválido argumento que sugere adicioná-lo ao comando pax (outra ferramenta para copiar arquivos), para que você possa manter seus nomes de arquivos completos em seu disco local, mas converter os nomes de arquivos durante a cópia para seu dispositivo USB:

pax -rw -s '/[?<>\:*|\"]/_/gp' *.mp3 /media/usb_device

Se os nomes de arquivos completos forem realmente importantes para você, sugiro que você reformate o pendrive USB para usar um sistema de arquivos nativo do Linux, como ext4 . (Existem drivers do Windows disponíveis para a família extN dos sistemas de arquivos, se necessário.)

    
por 01.08.2016 / 19:55
3

Definitivamente, é permitido ter ? em um nome de arquivo.

Do padrão POSIX:

Filename

A sequence of bytes consisting of 1 to {NAME_MAX} bytes used to name a file. The bytes composing the name shall not contain the <NUL> or <slash> characters. In the context of a pathname, each filename shall be followed by a <slash> or a <NUL> character; elsewhere, a filename followed by a <NUL> character forms a string (but not necessarily a character string). The filenames dot and dot-dot have special meaning. A filename is sometimes referred to as a "pathname component". See also Pathname.

Portanto, os únicos caracteres que um nome de arquivo não pode conter é / (significando um fim de string) e . (que é um separador de caminho). Além disso, os nomes dos arquivos .. e : são especiais e não podem ser usados pelos arquivos que você cria.

Alguns caracteres são especiais para o shell e precisam ser escapados ou citados apropriadamente para o shell para não tratá-los como padrões de globbing. O ponto de interrogação é um desses caracteres, como geralmente significa "qualquer caractere" em padrões de globalização.

Meu palpite é que o Thunar está optando por não lidar com esses nomes de arquivos como os caracteres ? e < (e > , " , | , \ , * e rename ) não são permitidos no Windows , e ele quer forçá-lo a usar nomes de arquivos portáveis entre o Windows e o Unix. Eu não conheço o raciocínio por trás disso, mas poderia ter algo a ver com o trabalho do Thunar em sistemas de arquivos compartilhados com máquinas Windows.

EDIT : Depois que a pergunta foi atualizada com mais informações, está claro que os arquivos precisarão estar em conformidade com as regras de nomenclatura do Windows, já que o sistema de arquivos é realmente um sistema de arquivos do Windows.

A resposta do @ roaima mostra como renomear arquivos usando o utilitário rename do Linux. Esta é uma outra solução que funcionará em sistemas sem bash , uma função fatmv , _ que renomeia arquivos contendo caracteres ilegais do Windows, alterando-os para sublinhados ( echo ):

function fatmv {
    name="$( basename "$1" )"
    destdir="$2"

    fat_name="$( tr ':?<>"|\*' '_' <<<"$name" )"

    if [[ -n "$destdir" ]]; then
      fat_name="$destdir"/"$fat_name"
    fi

    echo mv -f -- "$1" "$fat_name"
}

Se um segundo argumento for usado, isso é tratado como um diretório de destino para o qual o arquivo renomeado deve ser movido:

$ fatmv '<illegal>:filename?' /mount/fat_disk/
mv -f -- <illegal>:filename? /mount/fat_disk//_illegal__filename_

Teste isso como está e, em seguida, remova o %code% para que ele realmente faça alguma coisa.

    
por 01.08.2016 / 19:34
2

O ? é um caractere especial que tem importância no bash. Você pode trabalhar com ele, escapando com \

ou seja:

touch test\?

fará o arquivo:

test?

e você pode movê-lo com

mv test\? /new/loction/test\?

Editar: o mesmo para qualquer caractere especial, como .

Você também precisa dele para nomes de arquivo que contenham espaços

this is a file

teria que ser movido com:

mv this\ is\ a\ file <location>
    
por 01.08.2016 / 19:32
1

Para aplicar @roaimas resposta a todos os arquivos em um determinado diretório, você pode usar o comando

find /path/to/dir -exec rename 's/[?<>\:*|\"/_/g' {} \;

que aplica rename a todos os arquivos.

    
por 08.04.2017 / 15:22