Como posso renomear / mover um arquivo simplesmente “editando” seu caminho em um shell?

1

Considere o problema que você deseja renomear em um arquivo chamado some/path/File With A Long Name.txt into some/path/File with a very long name.txt . Para mim, essa sempre foi uma das poucas situações em que trabalhar com a linha de comando não tem a conveniência de navegadores de arquivos baseados em GUI, em que você pode simplesmente "editar" o nome de um arquivo em vez de passar o antigo e o novo nome. para mv .

Como já foi respondido por essa questão , a solução mais conveniente baseada em bash é usar a expansão de chaves . No entanto, isso ainda não é tão conveniente quanto simplesmente editar o nome do arquivo, especialmente em situações em que você tem um nome de arquivo muito longo com espaços e deseja apenas alterar alguns caracteres aqui e ali.

Minha pergunta é: Existe uma maneira de renomear arquivos "editando" o nome de alguma forma dentro do shell?

Aviso: Observe que essa é uma pergunta de resposta automática. Eu criei uma solução que funciona para mim, mas ainda estou aberto a qualquer ideia alternativa.

    
por bluenote10 07.11.2014 / 16:49

5 respostas

1

Normalmente, recuo para a conclusão de tabulação e edição readline. No entanto, aqui está uma reescrita bash do seu script python (requer versão 4 eu acho que para as opções de read fantasia)

mvInPlace () {
    local path newpath
    for path in "$@"; do
        if [[ ! -f "$path" ]]; then
            echo "No such file: $path" >&2
            continue
        fi
        echo "Old path: $path"
        read -p "New path: " -i "$path" -e newpath
        mv -v "$path" "$newpath"
    done
}
    
por 07.11.2014 / 17:26
1

Com zsh , um atalho prático para duplicar a palavra anterior (dependendo do seu modo zle) é Esc Ctrl _ , essa é a padrão no modo emacs . Você pode (re) definir isso sozinho. por exemplo. apenas Ctrl _ que é bom em um modo vi :

bindkey "^_" copy-prev-word
bindkey "^_" copy-prev-shell-word   # respects shell quote/escape

Com as ligações padrão readlinebash readline você pode "editar" corretamente e executar uma linha de comando com Meta- X Meta- E . Você pode querer definir as variáveis EDITOR ou VISUAL para o seu editor preferido, o que, esperamos, facilita a tarefa de duplicar uma palavra.

Você pode quase, mas não usa bem o zsh copy-prev-word no bash, mas sua noção do que uma palavra é nem sempre o fará feliz (estritamente alfanumérico):

bind "\C-_: copy-backward-word"

então Ctrl _ Ctrl Y para invocar.

Versões mais recentes do bash (desde 4.0) suportam palavras shell, mas não para cópia, apenas para motion / delete, então um leve hack é:

 bind "\C-_: shell-backward-kill-word"

Você pode cortar e depois colar (puxar) a palavra de volta duas vezes com o duplo Ctrl Y .

O Bash também permite ligar uma função shell, e nesse caso você pode fazer coisas criativas alterando as variáveis READLINE_LINE e READLINE_POINT , mas não tenho essa função para entregar agora . Aqui está uma função toy (bash-4.3 minimum) que duplica a última palavra shell, ou se a última palavra parece ser um comando sed , aplica-a à segunda última palavra shell e se substitui.

function _dupl() {
    [[ -z "${READLINE_LINE}" ]] && return                # empty, no action
    eval local -a aa=( "${READLINE_LINE}" ) 2>/dev/null  # split into words
    [[ ${#aa} -eq 0 ]] && return                         # parse problem

    if [[ "${aa[-1]:0:2}" == "s/" ]]; then               # sed 
        local _sed=$(sed -e "${aa[-1]}" <<< ${aa[-2]})
        unset aa[-1]                                     # remove last word
        printf -v READLINE_LINE "%q " "${aa[@]}"         # recreate line
        printf -v READLINE_LINE "%s%q" "${READLINE_LINE}" "$_sed"
    else
        printf -v READLINE_LINE "%s %q" "${READLINE_LINE}" "${aa[-1]}"
    fi
    READLINE_POINT=${#READLINE_LINE}   # move cursor to end
}
bind -x '"\C-_":"_dupl"'

Exemplo:

mv "some/path/File With A Long Name.txt" s/txt/bak/ Ctrl _

é então expandido na linha de entrada para:

mv some/path/File\ With\ A\ Long\ Name.txt some/path/File\ With\ A\ Long\ Name.bak

(você notará que as palavras citadas ficam com escape, pois printf %q é usado para expansão segura)

Esta última opção é possivelmente esticar demais o que se poderia considerar "em uma casca". se você tiver vim com o script netrw , basta editar o diretório como um arquivo:

  • vim .
  • usar recursos normais de pesquisa / navegação
  • use R para renomear o arquivo / diretório no cursor

Veja também: link

    
por 07.11.2014 / 20:07
0

O utilitário rename é bastante útil em situações como alterar maiúsculas e minúsculas.

Caso contrário, uso a expansão de tabulação para edições únicas:

mv File Separador File Separador

produzirá:

mv File\ With\ A\ Long\ Name.txt File\ With\ A\ Long\ Name.txt , que você pode editar na linha de comando como quiser.

    
por 07.11.2014 / 17:31
0

A solução que criei é um script Python simples que depende da funcionalidade da % móduloreadline . Eu uso assim: mvInPlace <PATH-TO-MOVE> . O script solicitará agora um novo nome / caminho, que é preenchido com o nome / caminho antigo. O módulo readline agora fornece os recursos completos de edição, por exemplo, você pode até mover o cursor por CTRL + ESQUERDA para pular para o próximo segmento da string. Para o prompt, o caminho fornecido é convertido em um caminho absoluto, o que também facilita mover algo para um caminho diferente.

#!/usr/bin/python

import os, sys, readline

if len(sys.argv) != 2:
  print "Usage: %s <PATH-TO-MOVE>" % os.path.basename(sys.argv[0])
  sys.exit(-1)

oldpath = os.path.abspath(sys.argv[1])
readline.set_startup_hook(lambda: readline.insert_text(oldpath))

print 'Old path: ' + oldpath
newpath = raw_input('New path: ')

cmd = 'mv -v "%s" "%s"' % (oldpath, newpath)
print "\n", cmd, "\n"
os.system(cmd)
    
por 07.11.2014 / 16:49
0

Eu sempre uso apenas a guia da seguinte forma:

nome do arquivo aqui: test file long name.txt

assim na linha de comando

ren test guia preenche automaticamente o nome completo do arquivo com caracteres de escape já existentes em seguida, tecle espaço para que eu possa começar o novo nome e novamente apenas digitando test tab me dá o mesmo nome de arquivo novamente com os caracteres de escape então é

User@server:~/$ test\ file\ long\ name.txt test\ file\ long\ name.txt

e eu posso apenas editar os poucos caracteres que eu preciso ou se eu quiser mudar o caminho eu uso o cp ao invés do ren e só uso para chegar ao espaço e adicionar qualquer novo path Desejo mover o arquivo para. em ambientes * nix não importa quanto tempo o comando é que você pode editar qualquer parte dele, desde que você não use / ou escape para uma nova linha de qualquer forma ele continuará indo para o infinito . Você também pode editar o nome do arquivo e depois adicionar o caminho depois de voltar para o espaço, se você quiser não apenas alterar alguns dos nomes do arquivo, mas também mudá-lo para um novo caminho [é claro que você precisa de cp e não ren e sim, se você alterar o nome do arquivo, você pode até mesmo usar o cp no mesmo diretório e nem mesmo usar ren.]

Eu faço tudo isso sem adicionar nada, por isso, se você se ajustar a fazê-lo desta maneira, mesmo se você acessar uma máquina de amigos, você não está tentando gostar de escrever seus scripts ou esquecer como fazer isso sem o script quando necessário.

Espero que ajude.

    
por 07.11.2014 / 18:27