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 / 1499949
Accepted
DealTime444
DealTime444
Asked: 2024-01-13 21:58:16 +0800 CST2024-01-13 21:58:16 +0800 CST 2024-01-13 21:58:16 +0800 CST

Reter a extensão do arquivo em um loop while simples (uma linha)

  • 772

Eu tenho uma string simples que renomeará todos os arquivos JPEG em uma pasta sequencialmente:

ls -v | cat -n | while read n f; do mv -n "$f" "pic-$n.jpg"; done

Mas tenho uma pasta com muitos tipos de arquivos diferentes. Existe uma string ou variável simples que eu possa substituir .jpgpara manter as extensões dos arquivos? Ou precisa ser um script completo agora? Eu gostaria de mantê-lo em uma única linha, se possível.

Exemplos

Digamos que eu tenha uma pasta como esta:

a long hash name.mp4
another name.m4v
video.mov
another name.mp4

e assim por diante. Quero renomear os arquivos da seguinte forma para que pareçam mais organizados e não tenham muitos caracteres, assim:

vid-1.mp4
vid-2.m4v
vid-3.mov
vid-4.mp4

Se eu usasse ls -v | cat -n | while read n f; do mv -n "$f" "vid-$n"; done, não teria extensões de arquivo. Quero manter as extensões dos arquivos porque às vezes é mais fácil abri-los.

Estou me perguntando principalmente se existe uma variável global no bash para definir extensões de arquivo

bash
  • 2 2 respostas
  • 43 Views

2 respostas

  • Voted
  1. Best Answer
    terdon
    2024-01-13T22:35:30+08:002024-01-13T22:35:30+08:00

    Não use um loop aqui, apenas use rename:

    $ ls
    'a bad name.png'   asdlha.gif   askd.png  'a worse'$'\n''name.jpg'   kasdjh.jpg
    
    $ rename -n 's/.*(\..+)/"pic-" . ++$a . "$1"/se' *
    a bad name.png -> pic0.png
    asdlha.gif -> pic1.gif
    askd.png -> pic2.png
    a worse
    name.jpg -> pic3.jpg
    kasdjh.jpg -> pic4.jpg
    

    Se parecer certo, execute novamente sem -nrenomear.

    Explicação:

    O renamecomando é um script perl que pode executar código perl para renomear arquivos. Aqui, estamos usando o operador de substituição ( s/old/new/) com algumas opções especiais:

    • Isso /sfaz com que o operador de substituição trate sua entrada como uma única linha, permitindo .a correspondência de caracteres de nova linha. Precisamos disso para lidar com nomes de arquivos com novas linhas, como fiz no exemplo acima.
    • Isso /enos permite avaliar o lado direito ( s/left/right/) como uma expressão perl. A expressão "pic-" . ++$a . "$1"significa "a string pic-, depois o valor da variável $aincrementado em um e o que quer que tenha correspondido entre parênteses no lado esquerdo". No nosso caso, a extensão.

    Em seguida, a expressão regular usada ( .*(\..+)) significa "zero ou mais caracteres ( .*) até o último .( \.corresponde a um literal .), depois um ou mais caracteres ( .+). Como o último \..+está entre parênteses, isso torna disponível o que foi correspondido (a extensão) como $1no lado direito.

    Depois de executar o comando acima sem o -n, fiquei com:

    $ rename  's/.*(\..+)/"pic-" . ++$a . "$1"/se' *
    terdon@oregano foo $ ls
    pic-1.png  pic-2.gif  pic-3.png  pic-4.jpg  pic-5.jpg
    

    Alternativamente, você pode fazer isso no shell com algo como:

    i=1; for file in *; do 
      ext="${file##*.}"; 
      mv -- "$file" pic-$((i++))."$ext"; 
    done
    

    Aqui, percorremos todos os arquivos (e diretórios, se você não quiser renomear os diretórios, tenha cuidado), salvando cada um como $file. Então, obtemos a extensão com ${file##*.}. O ${variable##pattern}formato removerá a correspondência mais longa patternda variável $variable. Ao usar ${file##*.}removemos tudo até o último ., deixando apenas a extensão que salvamos como $ext.

    A seguir, o mvcomando irá renomear $filepara pic-, mais o valor da variável $i, com a qual inicializamos i=1, incrementado em um, seguido de a .e da extensão.

    Assim como a renamesolução acima, esta também pode lidar com nomes de arquivos arbitrários:

    $ ls
    'a bad name.png'   asdlha.gif   askd.png  'a worse'$'\n''name.jpg'   kasdjh.jpg
    $ i=1; for file in *; do 
      ext="${file##*.}"; 
      mv -- "$file" pic-$((i++))."$ext"; 
    done
    $ ls
    pic-1.png  pic-2.gif  pic-3.png  pic-4.jpg  pic-5.jpg
    
    • 2
  2. steeldriver
    2024-01-13T23:31:45+08:002024-01-13T23:31:45+08:00

    Se você precisar especificamente que os arquivos sejam nomeados aritmeticamente na ordem de classificação da versão (como em ls -v), sugiro algo como

    printf '%s\0' *.* | sort -zV | {
      local n=1
      while IFS= read -r -d '' f; do 
        echo mv -nv -- "$f" "pic-$((++n)).${f##*.}"
      done
    }
    

    ou, se você quiser zerar os novos nomes (o que facilita a classificação subsequente), talvez

    printf '%s\0' *.* | sort -zV | { 
      local n=1
      while IFS= read -r -d '' f; do 
        printf -v p 'pic-%03d.%s' $((++n)) "${f##*.}"
        echo mv -nv -- "$f" "$p"
      done
    }
    

    Remova o echodepois de confirmar que os arquivos corretos serão processados ​​na ordem desejada. Se você não se importa com a legibilidade, é claro que pode escrevê-los como "uma linha", se desejar, por exemplo.

    printf '%s\0' *.* | sort -zV | { local n=1; while IFS= read -r -d '' f; do printf -v p 'pic-%03d.%s' $((++n)) "${f##*.}"; echo mv -nv -- "$f" "$p"; done; }
    
    • 2

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