Como renomear arquivos com espaços usando o shell do Linux?

28

Eu nomeei vários arquivos com espaços neles e quero substituir o espaço por _. No entanto, toda vez que escrevo um comando no shell com o nome do arquivo (por exemplo Spring 2011), o shell não reconhece o arquivo ou o diretório.

O que é que eu posso fazer sobre isto? Existe alguma maneira de usar o caractere unicode para um espaço?

Phil Braun
fonte
para renomear programaticamente arquivos N, use um bashloop for: veja minha solução aqui .
Trevor Boyd Smith

Respostas:

33

Escape do espaço, por exemplo Spring\ 2011, ou use aspas, por exemplo 'Spring 2011'. No futuro, normalmente é uma má idéia usar nomes de arquivos com espaços em qualquer * NIX.

Se você tiver rename, você pode usar isto:

rename ' ' '_' [filenames...]
Rafe Kettler
fonte
1
Você sabe que existe alguma maneira de fazer isso para todos os arquivos de uma só vez?
3
Por que é uma má ideia? É responsabilidade do programador manipular os nomes de arquivos corretamente.
Glenn Jackman
1
@rafe, realmente é propenso a erros para não manipular os nomes de arquivos corretamente na frente. O esforço extra ocorre quando é necessário depurar um script quando você simplesmente esquece de citar variáveis ​​contendo um nome de arquivo.
Glenn Jackman
3
Esta resposta parece não funcionar (no Ubuntu 12.04 LTS, pelo menos). A resposta do unutbu funciona bem.
DNA
1
isso só fez o primeiro espaço para mim ... o que não é útil (eu tenho renamea versão 2.23)
Trevor Boyd Smith
30

Se sua máquina tiver o comando rename , isso mudará todos os espaços para sublinhados em todos os arquivos / diretórios no diretório de trabalho atual:

rename 's/ /_/g' *
unutbu
fonte
Confirmado para trabalhar no Ubuntu 12.04
anthonygore 10/10
1
não funcionou para mim ... recebi um erro de "renomear: argumentos insuficientes". i tem versão rename --version rename from util-linux 2.23.2.
Trevor Boyd Smith
24

Se você não possui renameou prefere usar apenas o shell:

for f in *\ *; do mv "$f" "${f// /_}"; done

Quebrado:

  • *\ *seleciona todos os arquivos com um espaço em seu nome como entrada para o forloop.
  • As aspas "$f"são importantes porque sabemos que há um espaço no nome do arquivo e, caso contrário, ele apareceria com mais de 2 argumentos para mv.
  • ${f//str/new_str}é um recurso de substituição de string específico do bash. Todas as instâncias de strsão substituídas por new_str.
blahdiblah
fonte
2
isso funciona, mas para mim substitui apenas o primeiro espaço. se eu usar for f in *\ *; do mv "$f" "${f// /_}"; doneele funciona
billynoah
@billynoah Boa captura, atualizada.
precisa saber é o seguinte
@blahdiblah Muito obrigado! Você acabou de me poupar muito tempo!
Guerrilla
@blahdiblah sua solução é muito mais elegante que a minha solução . bom trabalho. Eu não acho que o globo loop for funcionaria ... então eu fiz o globo fora do loop for.
Trevor Boyd Smith
3

mv "Spring 2011.file" Spring_2011.file deve informar a linha de comando para usar a string entre aspas como uma única entrada.

rockerest
fonte
Esta é a única resposta que eu poderia começar a trabalhar.
blakeoft
1

Para renomear programaticamente N arquivos, você pode usar um bashloop for simples .

#!/bin/bash

set -eux

# find all your files by using a `grep` pattern
pattern="insert_filename_pattern_here" # you must enter your filename pattern here

# create an array of filenames and split on newlines
IFS=$'\n'
tmp=($(ls | grep ${pattern}))
unset IFS

# for each filename
for filename in "${tmp[@]}"; do
    # rename the filename to use "_" character instead of a " " character
    mv -v "${filename}" "${filename// /_}"
done

Se você tiver menos de 5 nomes de arquivos, poderá digitar manualmente todos os nomes de arquivos e usar o renamecomando como a solução acima sugere. Mas para mim ... eu prefiro a solução programática ... mesmo quando há apenas 4 arquivos.

ps

se você não estiver familiarizado com Basha expansão de parâmetro (ou seja ${filename// /_}), poderá usar o renamecomando:

if ((0)); then
    mv -v "${filename}" "${filename// /_}"
else
    rename ' ' '_' "${filename}"
fi
Trevor Boyd Smith
fonte