AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / ubuntu / Perguntas / 1537955
Accepted
Don Carpenter
Don Carpenter
Asked: 2025-01-13 03:30:58 +0800 CST2025-01-13 03:30:58 +0800 CST 2025-01-13 03:30:58 +0800 CST

Como alterar nomes de arquivos que possuem um espaço no nome usando um script

  • 772

Tenho alguns arquivos em ~home (em muitos subdiretórios) no meu sistema Ubuntu 22.04. Acredito que a maioria dos nomes de arquivo com espaços veio originalmente do Windows.

Estou encontrando os arquivos ofensivos com o seguinte comando find

encontrar . -nome "* *"

Qual é uma maneira de alterar os nomes para incluir um _ ou algum outro caractere em todos os arquivos que atualmente têm um espaço no nome?

Por exemplo, eu quero mudar

PEDIDO DE PÉS DE MÁQUINA MSC.pdf

para

MSC_MÁQUINA_PÉS_PEDIDO.pdf

Usando o comando find, determinei que tenho cerca de 600 arquivos que precisam ter seus nomes alterados, então gostaria de alguma maneira automatizada de alterar os nomes.

Os nomes de arquivos com espaços estão causando problemas quando executo determinados scripts.

Agradecemos antecipadamente pela sua ajuda.

bash
  • 3 3 respostas
  • 771 Views

3 respostas

  • Voted
  1. Best Answer
    choroba
    2025-01-13T03:51:02+08:002025-01-13T03:51:02+08:00

    Você pode usar a expansão de parâmetros para substituir espaços por sublinhados:

    find -name '* *' -exec bash -c 'mv "$1" "${1// /_}"' -- {} \;
    
    • ${1// /_}significa "substituir cada espaço no primeiro parâmetro por um sublinhado (veja Expansão de Parâmetros em man bash).
    • bash -cexecuta os comandos do primeiro argumento não-opcional. Aqui, o comando é o mvque substitui espaços por sublinhados.
    • O primeiro argumento após o argumento de comandos to bash -cnão é importante agora, então usei --. Os argumentos restantes são definidos como argumentos posicionais para o comando.
    • find -execexecuta o comando para cada arquivo encontrado. O {}é substituído pelo nome do arquivo, o final \;informa findonde o comando termina. Então, find chama bash -ce envia o nome do arquivo como o primeiro argumento, para que ele possa ser renomeado.

    Este encantamento complexo é necessário para preservar os espaços no primeiro argumento para mv.

    Se você quiser renomear subdiretórios também, você precisa usar -depthand -execdirem vez de -exec(caso contrário, o nome do diretório muda e o find não consegue mais encontrá-lo para trabalhar em seu conteúdo).

    Observe que alterar os nomes dos arquivos também pode causar problemas: se um programa espera que um arquivo exista com o nome fornecido, alterar o nome pode fazer o programa falhar.

    • 16
  2. Peter Cordes
    2025-01-13T18:16:12+08:002025-01-13T18:16:12+08:00

    perl-rename aka renameaka prenameé excelente para renomeação de arquivos de substituição de padrões. Veja https://francopasut.netlify.app/post/linux-rename-confusion/ re: os vários nomes sob os quais você pode encontrar esse comando, e que o util-linux costumava também enviar um renamecomando diferente que não usava regexes. De uma rápida olhada, acho que o Ubuntu agora o envia como rename. De uma antiga página de manual (do Trusty) , naquela época ele fazia parte do perlpacote; se ainda for o caso, você já o instalou.

    Ele pega uma declaração perl para ser aplicada a cada nome de arquivo em sua linha de comando. O s/regex/replacement/ operador opera implicitamente em $_(linha atual, neste caso nome de arquivo atual), então é altamente útil. (Você pode usar s{pat}{rep}separadores de padrões se quiser corresponder e substituir /em caminhos.) Veja https://linux.die.net/man/1/perlop para detalhes sobre o operador perl s//.

    Para o seu caso, basta executar prename 's/ /_/g' em quantos arquivos quiser ao mesmo tempo. Como no sed, o /gmodificador substitui cada ocorrência de uma correspondência. Usar find -execdirEnsures prenamesó vê o nome do arquivo, não os nomes dos diretórios, já que tentar mover foo bar/x y.txtpara foo_bar/x_y.txtfalharia, independentemente de foo bar/ter sido renomeado ainda (o diretório de origem ou de destino não existirá).

       find -depth  -name '* *'  -execdir prename -i  's/ /_/g' {} +
    

    -iprompts antes de sobrescrever um arquivo. Geralmente uma boa ideia se você não pretendia sobrescrever nada. Ele também tem uma opção -naka .--dry-run

    Não verifiquei a findpágina do manual sobre se -depthé necessário para correção se você for renomear diretórios conforme ele se repete. Não faz mal neste caso, então incluí.


    a resposta de choroba seria fork+exec bashe mvpara cada arquivo ser renomeado. prenamefaria apenas um pouco de processamento de texto e uma rename(2)chamada de sistema. E mais importante para uso interativo único, é uma linha de comando mais simples.

    Para ser justo, eu tive que usar -execdirno caso de diretórios que contêm espaços, o que eu só pensei na metade da escrita desta resposta. Não tenho certeza se -depthé necessário ou não para ambas as nossas respostas; isso se aplicaria de qualquer forma, eu acho.

    Em um caso mais simples, onde todos os arquivos estão em um diretório, você poderia simplesmente prename -i 's/ /_/g' *\ *usar uma expressão glob que corresponde aos nomes de arquivos com espaços.

    Ou com Bash set -o extglobhabilitado, prename ... **/*\ *para corresponder recursivamente. Mas isso permitirá que prename veja nomes de diretórios; se eles contiverem espaços, não funcionará a menos que você torne o código perl mais complicado para, por exemplo, separar o basename, modificá-lo e, em seguida, anexá-lo novamente. Ou você pode apenas executá-lo algumas vezes até parar de receber erros, pois os diretórios são renomeados para que o próximo nível de profundidade seja bem-sucedido.

    • 4
  3. steeldriver
    2025-01-14T09:40:54+08:002025-01-14T09:40:54+08:00

    Se você mudar para o zsh, poderá usar o módulo zmv contribuído:

    % autoload -Uz zmv        # normally this would go in your user's ~/.zshrc
    
    % zmv -n '(**/)(* *)(#q.D)' '$1${2// /_}'
    

    ( -né apenas para teste - remova-o quando estiver satisfeito que as operações de renomeação propostas estão corretas).

    O **operador ("globstar") faz a correspondência de padrões descer recursivamente em subdiretórios como o findcomando. Os dois primeiros conjuntos de parênteses capturam o diretório e o nome do arquivo em variáveis ​​numeradas separadas que podem ser usadas na sequência de substituição, enquanto o terceiro (#q.D)é um qualificador glob no qual

    • .restringe a correspondência a arquivos simples (como o finddo comando -type f)

    • Dinclui "dotfiles" (ocultos) (para consistência com sua findexpressão original - você pode omitir isso se não precisar corresponder a esses arquivos).

    A substituição $1${2// /_}concatena a parte do diretório não modificada com o nome do arquivo modificado. Você também pode escrever isso usando a expansão no estilo histórico, '$1${2:gs/ /_}'se preferir.

    Veja man zshcontrib e man zshexpn .

    • 0

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Existe um comando para listar todos os usuários? Também para adicionar, excluir, modificar usuários, no terminal?

    • 9 respostas
  • Marko Smith

    Como excluir um diretório não vazio no Terminal?

    • 4 respostas
  • Marko Smith

    Como descompactar um arquivo zip do Terminal?

    • 9 respostas
  • Marko Smith

    Como instalo um arquivo .deb por meio da linha de comando?

    • 11 respostas
  • Marko Smith

    Como instalo um arquivo .tar.gz (ou .tar.bz2)?

    • 14 respostas
  • Marko Smith

    Como listar todos os pacotes instalados

    • 24 respostas
  • Martin Hope
    Flimm Como posso usar o docker sem sudo? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    led-Zepp Como faço para salvar a saída do terminal em um arquivo? 2014-02-15 11:49:07 +0800 CST
  • Martin Hope
    ubuntu-nerd Como descompactar um arquivo zip do Terminal? 2011-12-11 20:37:54 +0800 CST
  • Martin Hope
    TheXed Como instalo um arquivo .deb por meio da linha de comando? 2011-05-07 09:40:28 +0800 CST
  • Martin Hope
    Ivan Como listar todos os pacotes instalados 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    David Barry Como determino o tamanho total de um diretório (pasta) na linha de comando? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher "Os seguintes pacotes foram retidos:" Por que e como resolvo isso? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford Como os PPAs podem ser removidos? 2010-07-30 01:09:42 +0800 CST

Hot tag

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve