Escreva um programa que reverta o nome do arquivo de origem

27

Em um único arquivo, escreva um programa que não exija entrada e não produza saída. Quando executado, ele deve reverter o nome do arquivo em que está, independentemente do nome , sem alterar o código ou produzir outros efeitos colaterais duradouros.

Qualquer maneira de conseguir isso é bom. Só importa que, uma vez que o programa seja executado, a única alteração duradoura seja que o nome do arquivo tenha sido revertido. por exemplo, nenhum novo arquivo deve estar no diretório

A execução do programa novamente deve reverter o nome. De fato, o programa deve poder ser executado arbitrariamente várias vezes.

Para os propósitos deste desafio:

  • Você pode presumir que os nomes de arquivos são sempre cadeias de letras minúsculas (az) entre 1 e 127 caracteres. (Se o seu idioma exigir que os arquivos tenham extensões para executar, basta inverter a parte antes da extensão, por exemplo, mycode.batedocym.bat.)
  • Você pode assumir que o arquivo de código está em um diretório por si só, para que não tenha conflitos de nomes (exceto com ele próprio).
  • Você não pode assumir que o nome do arquivo não é um palíndromo, ou seja, o mesmo quando invertido. Nomes de arquivos que são palíndromos devem funcionar tão bem quanto aqueles que não são.
  • Você pode ler o conteúdo ou os metadados do seu arquivo. Não há restrições de aqui.
  • Você pode presumir que seu programa será executado em um sistema operacional comum, moderno e comum (por exemplo, Windows / Linux), pois nem todos os shells têm o mesmo conjunto de comandos.

Como um exemplo concreto, digamos que você tenha um programa Python em um arquivo chamado mycodeem seu próprio diretório. Corrida

python mycode

no terminal deve resultar na reversão do nome do arquivo para edocym. O arquivo edocymdeve estar sozinho em seu diretório - nenhum arquivo nomeado mycodedeve existir mais. Corrida

python edocym

irá reverter o nome para mycode, quando o processo pode ser repetido indefinidamente.

Se o mesmo arquivo Python foi renomeado racecar(sem alterar o código) e, em seguida, execute

python racecar

nada deve mudar visivelmente, já que "carro de corrida" é um palíndromo. O mesmo se aplica se o nome do arquivo for, digamos, aou xx.

O código mais curto em bytes vence. O desempatador é a resposta votada mais alta.

Passatempos de Calvin
fonte
O diretório de trabalho atual é importante?
Brad Gilbert b2gills
@ BradGilbertb2gills Você deve poder copiar a pasta com o programa para outro lugar e ainda assim fazê-lo funcionar (supondo que você tenha permissões e outros enfeites). Você pode assumir o diretório de trabalho do shell será a pasta o arquivo está no.
Calvin Hobbies
6
E se estivermos usando uma linguagem compilada? Como o executável afeta suas regras?
EMBLEMA
Pedido para esclarecer 'não aceita entrada e não produz saída'. Tecnicamente, o nome do arquivo é uma entrada que precisa ser recuperada do sistema de arquivos e o nome alterado deve ser enviado ao sistema de arquivos. Estes são entrada e saída. Pode valer a pena especificar que nenhuma outra saída é permitida.
atk
Além disso, você considera o uso de processos filho uma violação das regras de entrada / saída? Ou seja, chamar um processo separado para executar parte da tarefa, como reverter o nome, exigiria enviar ao outro processo o nome (saída do seu código e entrada para o aplicativo) e receber o valor do processo (saída do processo e entrada para o aplicativo).
atk

Respostas:

41

Bash + utilitários linux comuns, 13 bytes

Meu método é semelhante ao do DigitalTrauma, mas um pouco mais curto devido ao pipe com ls:

mv * `ls|rev`
Julie Pelletier
fonte
Oh muito bom.
Digital Trauma
20
Bem-vindo à programação de quebra-cabeças e código de golfe! Esta é uma primeira resposta muito boa. :)
Alex A.
1
Só funciona se não houver outro arquivo no diretório
WGroleau
1
@WGroleau && terdon: ambos os seus comentários estão certos, mas a pergunta já lida com essas duas suposições.
Julie Pelletier
@JuliePelletier ah, sim, você está certo. Perdi que os nomes dos arquivos só podem consistir em letras minúsculas.
terdon
14

C #, 153 bytes

void f(){var x=System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name;File.Move(x,new string(x.Reverse().ToArray()).Substring(4)+".exe");}

OO é legal e tudo até você ter uma variável definida:

System.Reflection.Assembly.GetExecutingAssembly (). ManifestModule.Name

isso é apenas dizer

downrep_nation
fonte
12

Bash + utilitários linux comuns, 15

  • 1 byte salvo graças a @Dennis

Supõe que o script esteja em um diretório por si só.

mv * `rev<<<$0`
Trauma Digital
fonte
6
Você pode assumir que o arquivo de código está em um diretório por si só , portanto, $0pode ser substituído por *.
Dennis
Desculpe, mas há um pequeno bug em sua atualização e ele não funciona como está. A correção mais simples é voltar mais perto do que você tinha antes e $0não da última *.
Julie Pelletier
@JuliePelletier Parecia funcionar antes quando eu tentei, mas sim, você está certo - * a expansão globbing não acontece à direita de uma <<<.
Digital Trauma
7

Julia, 51 bytes

d,f=splitdir(@__FILE__)
cd(d)do
mv(f,reverse(f))end

Este programa deve ser independente do sistema operacional, embora tenha sido testado apenas no OS X.

Ungolfed:

# Get the directory and file name of the current source file
d, f = splitdir(@__FILE__)

# Change the working directory temporarily to d
cd(d) do
    # Overwrite the file with the reverse of its name
    mv(f, reverse(f))
end
Alex A.
fonte
8
Parabéns! 20k !!!
Luis Mendo
A maioria das respostas parece assumir que o arquivo está no diretório atual, portanto, não acho que você precise do arquivo cd. Nesse caso, f=readdir()[]seria ainda mais curto.
Dennis
6

MATLAB, 50 46 bytes

e='.m';x=mfilename;movefile([x e],[flip(x) e])

Obrigado ao @Suever por remover 4 bytes e pelos testes!

Testado no OS X El Capitan e Debian Jessie, ambos com a versão R2014a do Matlab.

No Windows, 'f'é necessário um sinalizador ( e='.m';x=mfilename;movefile([x e],[flip(x) e]),'f') para alterar o nome do arquivo enquanto o arquivo está sendo usado.

Como funciona

e='.m';                       % Store file extension '.m' in variable `e`
x=mfilename;                  % Get name of file being run, without the extension
movefile([x e],[flip(x) e])   % Move (rename) file. `flip` is used for reversing the
                              % name without extension. [...] is (string) concatenation
Luis Mendo
fonte
Em que sistema operacional você 'f'é necessário?
Suever
@Suever Windows. Não é necessário no Mac?
Luis Mendo
Não é necessário no Mac do Linux, ao que parece.
Suever
@ Obrigadoever! 4 bytes de desconto :-)
Luis Mendo
@Suever Você pode indicar o SO exato em que isso funciona?
Luis Mendo
4

Ruby, 24 bytes

File.rename$0,$0.reverse

Bastante auto-explicativo. ( $0é o nome do arquivo que está sendo executado.)

Execute com ruby whateverum diretório de trabalho do diretório que contém o arquivo.

Maçaneta da porta
fonte
4

Lote, 109 bytes

@echo off
set f=%0
set r=
:l
set r=%f:~0,1%%r%
set f=%f:~1%
if not .%f%==. goto l
ren %0.bat %r%.bat

Nota 1: Os arquivos em lote devem terminar em .bat; pressupõe-se que o arquivo em lotes seja executado por seu nome sem extensão e que .batnão seja revertido. Por exemplo, reversetentaria renomear reverse.batpara esrever.bat.
Nota 2: CMD.EXEerros após renomear o arquivo em lotes. ( COMMAND.COMnão seria, exceto que é incapaz de manipulação de string em primeiro lugar.)

Editar: salvou 2 bytes usando a garantia de que o nome do arquivo é alfabético (com base no comentário de @ CᴏɴᴏʀO'Bʀɪᴇɴ).

Neil
fonte
3
1. POR QUE VOCÊ NÃO ESTÁ GRITANDO? 2. Eu acho que você pode salvar um byte fazendoif ]%f% NEQ ] goto l
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Ah, sim, o nome do arquivo é alfabético, por isso posso salvar 2 bytes, mas obrigado pela dica.
Neil
1
VOCÊ PRECISA DE GRITO DE LOTE menos que esteja usando OOBL AKA SMALLTALK-80
cat
4

C, 102 bytes

main(c,v)char**v;{char*b=strdup(*v),*n=strrchr(*v,47),*t=strchr(b,0);for(;*++n;*--t=*n);rename(*v,b);}

Demolir:

                            // No #include lines required (for GCC at least)
main(c,v)char**v;{          // K&R style function to save 2 bytes
    char*b=strdup(*v),      // Duplicate args[0] (script path)
        *n=strrchr(*v,47),  // Find last "/" in input
        *t=strchr(b,0);     // Go to end of output string
    for(;*++n;*--t=*n);     // Reverse input into output character-by-character
    rename(*v,b);           // Rename the file
}                           // Implicit return 0

Finalmente, um desafio em que C não é (tão irremediavelmente) não competitivo!


Se tomarmos "Você pode assumir o diretório de trabalho do shell será a pasta o arquivo está em" para significar que o programa vai ser sempre invocado como ./myexecutable, podemos simplificar *n=strrchr(*v,47)para *n=*v+1salvar 10 caracteres, mas isso não é inteiramente válido ( pode ser invocado como ././myexecutable, por exemplo).


Além disso, se você deseja manter uma extensão de arquivo (por exemplo, ".out") intacta, pode mudar *t=strchr(b,0)para *t=strrchr(b,46), custando 2 bytes. Não é necessário.

Dave
fonte
Bom - eu nunca tinha visto o que renameacontece se src == dest; parece que você satisfaz a restrição do palíndromo gratuitamente.
Toby Speight
Observe que isso requer um sistema de arquivos em que o codepoint 47 seja o separador. Eu acho que isso inclui POSIX (ou faz que permitem EBCDIC /em um caso de canto?)
Toby Speight
@TobySpeight sim, verifiquei gnu.org/software/libc/manual/html_node/Renaming-Files.html para obter alguns esclarecimentos, mas o mais próximo que encontrei foi "Um caso especial para renomear é quando oldname e newname são dois nomes para o mesmo arquivo A maneira consistente de lidar com esse caso é excluir o nome antigo. No entanto, neste caso, o POSIX exige que a renomeação não faça nada e relate o sucesso - o que é inconsistente. Não sabemos o que seu sistema operacional fará. ", Então acho que há uma chance externa de excluir o arquivo em sistemas não compatíveis com POSIX. Então, sim, o código real deve verificar!
Dave
Acabei de verificar linux.die.net/man/3/rename e ele confirma que o Linux lida com POSIX em conformidade: "Se o argumento antigo e o novo argumento resolverem o mesmo arquivo existente, rename () retornará com sucesso e não executará nenhum outro açao."
Dave
Eu estava na página de manual do Debian: "Se oldpathe newpathexistem links físicos referentes ao mesmo arquivo, rename()nada faz e retorna um status de sucesso" - se as strings são idênticas, elas se referem ao mesmo arquivo.
Toby Speight
3

Vitsy + * sh, 15 bytes

iG:`?r.iG' mr',

Explicação

iG:`?r.iG' mr',
i               Push -1 to the stack. (this assumes that no arguments are passed)
 G              Get the use name of the class specified by the top item of the
                stack. (-1 refers to the origin class, so this class)
  :             Duplicate stack and jump to it.
   `            Read a file with the current stack as its name, replacing the stack
                with the file's contents.
    ?           Shift one stack to the right.
     r          Reverse the current stack.
      .         Write a file with the name specified by the top stack and the
                contents as the second-to-top stack.
       iG       Get the name of the current class again.
         ' mr'  Push 'rm ' to the stack.
              , Execute the current stack as a command.

Observe que este envio deve usar a versão não segura do Vitsy (não pode ser feito no Try It Online!)

Addison Crump
fonte
3

Perl 5, 18 bytes

Um pouco como o Ruby (run perl nameofscript):

rename$0,reverse$0

Levar em consideração um caminho possível é mais feio (47 bytes)

($a,$b)=$0=~/(.*\/)?(.*)/;rename$0,$a.reverse$b
ilkkachu
fonte
1
Olá, e bem-vindo ao PPCG! Ótimo primeiro post!
NoOneIsHere
2

V , 29 26 bytes

:se ri
izyw:!mv z "
dd

Como contém imprimíveis, aqui está um dump hexadecimal:

00000000: 3a73 6520 7269 0a69 127a 1b79 773a 216d  :se ri.i.z.yw:!m
00000010: 7620 127a 2012 220a 6464                 v .z .".dd

Nota: isso não será executado no v.tryitonline.net, pois o TIO não permite o acesso ao arquivo.

Explicação:

:se ri            "Turn on 'reverse mode' (all text is inserted backwards)
i<C-r>z<esc>      "Enter the path to the file in reverse
yw                "Yank a word. This first word is the name we will save the new file as

"Run an "mv" in the terminal with the contents of register 'z' (the path to the file)
"And the contents of register '"' (the word we yanked)
:!mv <C-r>z <C-r>"

dd                "Delete a line so that we don't have any text printed.
DJMcMayhem
fonte
2

Python 3, 105 bytes

import os;a=__file__.split('\\')[::-1][0].split('.');os.rename('.'.join(a),'.'.join([a[0][::-1],a[1]]))

-Alex.A removeu 1 byte.

-O Trauma digital me mostrou os.rename (), que removeu 62 bytes.

-muddyfish removeu 7 bytes.

Magenta
fonte
Eu acho que você pode salvar um byte, removendo o espaço após a vírgula noimport
Alex A.
import os,sys;f=sys.argv[0];os.rename(f,f[::-1])deve fazer o truque para 48 bytes
Digital Trauma
doing f [:: - 1] inverte não apenas o nome do arquivo, mas todo o caminho. No entanto, obrigado por me apresentar o recurso os.rename ().
Magenta
@ Magenta Para mim, sys.argv[0]apenas retorna o nome do arquivo apenas sem o caminho quando o script é executado diretamente. Helka indicado este é ok
Digital Trauma
@DigitalTrauma quando executei o programa por si próprio, sys.arg [0] retornou o caminho completo. Vou adicionar uma segunda solução em que sys.argv [0] é apenas o nome do arquivo.
Magenta
2

PHP, 84, 70, 54 bytes

rename($f=__FILE__,strrev(basename($f,$e='.php')).$e);


EDIT: removido 14 bytes graças a insertusernameherenos comentários
EDIT: removido 16 bytes graças a Martijnnos comentários

tttony
fonte
2
Você pode obtê-lo para baixo para 70 bytes : rename($f=__FILE__,__DIR__."/".strrev(pathinfo($f)[filename]).".php");.
insertusernamehere
Excelente !!! mas seu código é melhor, uau, você tem 31 bytes
tttony 13/06
Você não pode torná-lo relativo? Você salvaria 7 bytes:rename($f=__FILE__,"./".strrev(pathinfo($f)[filename]).".php");
Martijn
ou ainda menor:rename(__FILE__,strrev(basename(__FILE__,'.php')).'.php');
Martijn
Legal! Adicionando vars que eu tenho agora 54 bytes
tttony
2

PowerShell, 39 bytes

mi *(-join((ls).name)[-5..-999]+'.ps1')
Bevo
fonte
Olá, e bem-vindo ao PPCG! Bom primeiro post!
Rɪᴋᴇʀ
2

Python 2 , 41 bytes

import os;s=__file__;os.rename(s,s[::-1])

Demo no Bash.

O Python realmente não se importa com a extensão do arquivo, para que possamos virar o nome inteiro.

Bubbler
fonte
1

PHP, 31 bytes

Acho que não há muito a explicar:

rename($x=$argv[0],strrev($x));
insertusernamehere
fonte
1

Perl 6 ,  70   27 bytes

Se fosse necessário trabalhar em um diretório de trabalho diferente, você precisaria de algo como isto:

$_=$*PROGRAM;.rename: .basename.flip.IO.absolute: .absolute.IO.dirname

Como o diretório de trabalho será o mesmo do programa, ele pode ser simplificado para apenas:

$_=$*PROGRAM;.rename: .flip

Explicação:

$_ = $*PROGRAM;  # IO::Path object

$_.rename:
    $_.basename
      .flip      # reverse characters
      .IO        # turn into an IO object (IO::Path)
      .absolute: # turn it into an absolute path Str in the following dir
        $_.absolute.IO.dirname
Brad Gilbert b2gills
fonte
1

JavaScript (Nó), 108 104 68 bytes

36 bytes salvos, graças ao Downgoat!

Versão do Windows:

require("fs").rename(F=__filename,F.split(/.*\\|/).reverse().join``)

Outra versão:

require("fs").rename(F=__filename,F.split(/.*\/|/).reverse().join``)
Conor O'Brien
fonte
@ Upgoat Eu não preciso, acho que não. Estou correspondendo jsno final do caminho do arquivo, precedido por um caractere. Isso sempre será um ..
Conor O'Brien
1

JavaScript ES6 (Node.js) 70 bytes

Não Regex Yay!

require("fs").rename(a=__filename,[...a].reverse().join``.split`/`[0])

Qualquer ajuda é apreciada

MayorMonty
fonte
1

PowerShell v4 +, 68 bytes

$a,$b=($c=(ls).Name)-split'\.';mv $c "$(-join($a[$a.length..0])).$b"

Só funciona porque é garantido que o script esteja em um diretório por si só. Executa um ls(alias para Get-ChildItem) e obtém o .Name(s) objeto (s) resultante (s). Nós armazenamos que, em $ce, em seguida, -splitque no período literal para obter o nome do arquivo e extensão, e armazenar aqueles em $ae $b, respectivamente.

A seguir, o comando mv(apelido para Move-Item), para o qual estamos indo $cpara $a(revertido) .$b.

Exemplo

PS C:\Tools\Scripts\golfing\reverse> ls

    Directory: C:\Tools\Scripts\golfing\reverse

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         6/13/2016   7:58 AM         88 reverse.ps1

PS C:\Tools\Scripts\golfing\reverse> .\reverse.ps1

PS C:\Tools\Scripts\golfing\reverse> ls

    Directory: C:\Tools\Scripts\golfing\reverse

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         6/13/2016   7:58 AM         88 esrever.ps1
AdmBorkBork
fonte
1

Python (2.7 ou 3.4 ou superior), 61 49 bytes

Acredito que isso esteja próximo da solução ideal para Python:

import os;a=__file__;os.rename(a,a[-4::-1]+".py")

Inspirado na s4b3r6resposta de, mas usa o fatiamento de lista em vez de reverso e salva __file__em uma variável para salvar bytes ao usá-lo duas vezes.

Nota: Isso pressupõe que o nome do arquivo seja sempre *.py. Uma solução um pouco mais genérica que possa lidar com qualquer extensão de arquivo de dois caracteres seria a[-3:]substituí-la ".py", ao custo de 1 byte extra.

Atualização: salvou 12 bytes usando o truque de fatiar lista a[-4::-1]para remover a extensão do arquivo, em vez de dividir e reverter com a.split(".")[0][::-1].

Jaden Burt
fonte
1

Powershell, 112 bytes

Eu não vou vencer os cmds unix, apenas adicionando meus dois pence por diversão :-)

gci * | % { $n=($_.basename[-1..-(($_.basename).length)] -join “”)+$_.Extension; mv -Path $_.Fullname -Dest $n }
rb101
fonte
Bem-vindo ao PPCG! Exigimos que as respostas exibam a pontuação deles, então eu a editei para você. Além disso, você pode formatar seu código destacando-o e selecionando o botão que se parece com colchetes {}ou adicionando 4 espaços antes do código.
FryAmTheEggman
0

PowerShell, 50 bytes

mv *(-join($f=(ls).BaseName)[$f.Length..0]+'.ps1')

Há apenas um arquivo, portanto, o mv *curinga do shell terá apenas um resultado. O nome do destino é o (ls).basenameque lista todos os arquivos (alias de 'dir'), chama a propriedade BaseName - e, como existe apenas um arquivo, o PowerShell descompacta a matriz de 1 item em uma sequência. Armazene esse nome de arquivo $fe indexe-o com uma contagem regressiva e -joinos caracteres invertidos retornem para uma sequência. Adicione o .ps1sufixo obrigatório .

TessellatingHeckler
fonte
0

AutoIt, 45 bytes

$a=@ScriptName
FileMove($a,StringReverse($a))
Daniel
fonte
0

Python 2.7, 68 bytes

importar os; a = __ arquivo __; os.rename (a, a.split ("\\") [- 1] [: - 3] [:: - 1] + ". py")

Este é provavelmente o melhor que posso conseguir. Eu apenas me provei errado.

Alex
fonte
0

Python (2 e 3), 88 78 bytes

import os;os.rename(__file__,''.join(reversed(__file__.split(".")[0]))+".py"))

Explora o fato de que o nome do arquivo é fornecido pelo sys.argv (como o diretório de trabalho é a pasta em que o arquivo está) e utiliza o os.rename. Irritantemente, o reverso retorna um iterador, então temos que usar a junção.

Editar: salvou 10 bytes usando __file__ em vez de sys.argv [0], conforme sugerido por @muddyfish para @DigitalTrauma.

s4b3r6
fonte
0

tcl, 42

file rename $argv0 [string reverse $argv0]
sergiol
fonte
0

Script do Visual Basic, 44 bytes

WScript.Echo(StrReverse(WScript.ScriptName))

Exemplo de saída para o arquivo chamado reverse.vbs(Executar com cscript):

sbv.esrever
Gabriel Mills
fonte
0

sfk , 83 bytes

list -maxfiles=1 . +setvar n +getvar n +swap +setvar m +ren -var . /#(n)/#(m)/ -yes

Experimente online!

Furioso
fonte
0

SmileBASIC 60 bytes

P$=PRGNAME$()FOR I=1-LEN(P$)TO.Q$=Q$+P$[-I]NEXT
RENAME P$,Q$

Alternativo:

P$=PRGNAME$()T$=P$*1WHILE""<T$Q$=Q$+POP(T$)WEND
RENAME P$,Q$
12Me21
fonte