Напишите программу, которая меняет имя своего исходного файла.


27

В одном файле напишите программу, которая не требует ввода и не производит вывода. При запуске он должен полностью изменить имя файла, в котором он содержится, независимо от того, какое это имя , без изменения кода или создания других длительных побочных эффектов.

Любой способ достижения этого хорошо. Имеет значение только то, что после запуска программы единственным долговременным изменением является изменение ее имени файла. например, в каталоге не должно быть новых файлов.

Повторный запуск программы должен вернуть имя обратно. Действительно, программа должна запускаться произвольно много раз.

Для целей этой задачи:

  • Вы можете предположить, что имена файлов - это всегда строчные буквы (az) длиной от 1 до 127 символов. (Если ваш язык требует, чтобы файлы имели расширения для запуска, просто переверните деталь перед расширением, например mycode.batedocym.bat.)
  • Вы можете предположить, что файл кода находится в каталоге сам по себе, поэтому у него не будет конфликтов имен (кроме как с самим собой).
  • Вы не можете предполагать, что имя файла не является палиндромом, то есть то же самое при обращении. Имена файлов, которые являются палиндромами, должны работать так же, как и те, которые не работают.
  • Вы можете прочитать содержимое вашего файла или метаданные. Там нет ограничений здесь.
  • Вы можете предположить, что ваша программа будет работать в конкретной современной обычной операционной системе (например, Windows / Linux), поскольку не все оболочки имеют одинаковый набор команд.

В качестве конкретного примера, скажем, у вас есть программа на Python в файле, который называется mycodeв своем собственном каталоге. Бег

python mycode

в терминале должно привести к обратному имени файла edocym. Файл edocymдолжен быть один в своем каталоге - файл с именем mycodeбольше не должен существовать. Бег

python edocym

обратится к имени обратно mycode, после чего процесс может повторяться бесконечно.

Если тот же файл Python был переименован racecar(без изменения кода), а затем запустить

python racecar

ничего не должно заметно измениться, так как «гоночный автомобиль» - палиндром. То же самое происходит, если имя файла было, скажем, aили xx.

Самый короткий код в байтах побеждает. Ответ Tiebreaker выше.


Имеет ли значение текущий рабочий каталог?
Брэд Гилберт b2gills

@ BradGilbertb2gills Вы должны быть в состоянии скопировать папку с программой куда-то еще и все еще иметь ее работу (при условии, что у вас есть разрешения и еще много чего). Вы можете предположить, что рабочим каталогом оболочки будет папка, в которой находится файл.
Увлечения Calvin

6
Что если мы используем скомпилированный язык? Как исполняемый файл влияет на ваши правила?
ЭМБЛЕМА

Запрос на уточнение «не принимает ввод и не производит вывод». Технически, имя файла является вводом, который должен быть извлечен из файловой системы, а измененное имя должно быть отправлено в файловую систему. Это вход и выход. Возможно, стоит указать, что никакие другие выходы не допускаются.
atk

Кроме того, считаете ли вы использование дочерних процессов нарушением правил ввода / вывода? То есть вызов отдельного процесса для выполнения части задачи, такой как изменение имени, потребует отправки имени другого процесса (вывод из вашего кода и ввод в приложение) и получения значения от процесса (вывод процесса). и вход в приложение).
atk

Ответы:


41

Bash + общие утилиты Linux, 13 байт

Мой метод похож на @ DigitalTrauma, но немного короче из-за канала с ls:

mv * `ls|rev`

Очень хорошо.
Цифровая травма

20
Добро пожаловать в Программирование Пазлов и Code Golf! Это очень хороший первый ответ. :)
Алекс А.

1
Работает только в том случае, если в каталоге нет другого файла.
WGroleau

1
@WGroleau && terdon: оба ваших комментария верны, но этот вопрос уже отвечает этим двум предположениям.
Джули Пеллетье

@JuliePelletier ах, да, ты совершенно прав. Я пропустил, что имена файлов могут состоять только из строчных букв.
тердон

14

C #, 153 байта

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

ОО это круто и все, пока у вас не определится переменная:

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

это просто значит


12

Bash + общие утилиты Linux, 15

  • 1 байт сохранен благодаря @Dennis

Предполагается, что скрипт находится в каталоге сам по себе.

mv * `rev<<<$0`

6
Вы можете предположить, что файл кода находится в каталоге сам по себе , поэтому $0его можно заменить на *.
Деннис

Извините, но в вашем обновлении есть небольшая ошибка, и она не работает как есть. Самое простое решение - вернуться ближе к тому, что было раньше, $0а не к последнему *.
Джули Пеллетье

@JuliePelletier Похоже, это сработало и раньше, когда я попробовал, но да, вы правы - * всплывающее расширение не происходит справа от a <<<.
Цифровая травма

7

Юлия, 51 байт

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

Эта программа должна быть независимой от операционной системы, хотя она была протестирована только на 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

8
Congrats! 20k !!!
Луис Мендо

Большинство ответов, кажется, предполагают, что файл находится в текущем каталоге, поэтому я не думаю, что вам нужно cd. В этом случае f=readdir()[]будет еще короче.
Деннис

6

MATLAB, 50 46 байтов

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

Спасибо @Suever за удаление 4 байтов и за тестирование!

Протестировано на OS X El Capitan и Debian Jessie, оба с версией Matlab R2014a.

В Windows необходим флаг 'f'( e='.m';x=mfilename;movefile([x e],[flip(x) e]),'f'), чтобы изменить имя файла во время его использования.

Как это работает

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

На какой ОС вы 'f'работаете?
Suever

@ Windows для Windows. Разве это не нужно на Mac?
Луис Мендо

Не требуется на Mac Linux, кажется.
Suever

@ Спасибо спасибо! 4 байта прочь :-)
Луис Мендо

@Suever Можете ли вы указать точную ОС, на которой он работает?
Луис Мендо

4

Рубин, 24 байта

File.rename$0,$0.reverse

Довольно очевидный. ( $0это имя исполняемого файла.)

Запустите с ruby whateverрабочим каталогом каталог, который содержит файл.


4

Пакетный, 109 байтов

@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

Примечание 1: Пакетные файлы должны заканчиваться .bat; Предполагается, что пакетный файл выполняется по имени без расширения и .batне подлежит обращению. Например, reverseпопытался бы переименовать reverse.batв esrever.bat.
Примечание 2: CMD.EXEошибки после переименования командного файла. ( COMMAND.COMнет, за исключением того, что он не способен манипулировать строками).

Изменить: 2 байта сохранены, используя гарантию, что имя файла является буквенным (на основе комментария @ CᴏɴᴏʀO'Bʀɪᴇɴ).


3
1. Почему ты не кричишь? 2. Я думаю, что вы можете сохранить байт, выполнивif ]%f% NEQ ] goto l
Конор О'Брайен

@ CᴏɴᴏʀO'Bʀɪᴇɴ Ах, да, имя файла буквенное, поэтому я могу сэкономить 2 байта, но спасибо за подсказку.
Нил

1
ВАМ НЕОБХОДИМО ВЫСТУПАТЬ В ПАРТИИ, ЕСЛИ НЕ ИСПОЛЬЗУЕТЕ OOBL AKA SMALLTALK-80
кошка

4

C, 102 байта

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

Сломать:

                            // 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

Наконец, задача, в которой С не является (совершенно безнадежно) неконкурентоспособной!


Если мы возьмем «Можно предположить , рабочий каталог оболочки будет папка файл в» означает , что программа всегда будет служить ./myexecutable, мы можем упростить , *n=strrchr(*v,47)чтобы *n=*v+1спасти 10 символов, но это не совсем правомочно ( это может быть вызвано как ././myexecutable, например).


Кроме того, если вы хотите сохранить расширение файла (например, «.out»), вы можете изменить его *t=strchr(b,0)на *t=strrchr(b,46)2 байта. Не обязательно, хотя.


Хорошо - я никогда не смотрел, что renameделает, если src == dest; кажется, что вы удовлетворяете ограничению палиндрома бесплатно.
Тоби Спейт

Обратите внимание, что для этого требуется файловая система, где кодовая точка 47 является разделителем. Я думаю, что это включает POSIX (или это позволяет EBCDIC /в угловом случае?)
Тоби Спейт

@TobySpeight да, я проверил gnu.org/software/libc/manual/html_node/Renaming-Files.html для некоторых разъяснений, но самое близкое, что я нашел, было: «Один особый случай для переименования - это когда oldname и newname - это два имени для одного файла Последовательный способ справиться с этим делом - удалить старое имя. Однако в этом случае POSIX требует, чтобы переименование ничего не делало и сообщало об успешном выполнении, что противоречиво. Мы не знаем, что будет делать ваша операционная система. " внешняя вероятность, что он просто удалит файл в системах, не поддерживающих POSIX. Так что да, настоящий код должен проверить!
Дэйв

Я только что проверил linux.die.net/man/3/rename, и это подтверждает, что Linux обрабатывает его POSIX-совместимо: «Если старый аргумент и новый аргумент преобразуются в один и тот же существующий файл, rename () должна успешно вернуться и не выполнять никаких других действие «.
Дейв

Я шел с man-страницей Debian: «Если oldpathи newpathсуществуют жесткие ссылки, ссылающиеся на один и тот же файл, то rename()ничего не делает и возвращает статус успеха» - если строки идентичны, они ссылаются на один и тот же файл.
Тоби Спейт

3

Витси + * ш, 15 байт

iG:`?r.iG' mr',

объяснение

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.

Обратите внимание, что в этом представлении должна использоваться небезопасная версия Vitsy (это невозможно сделать в Try It Online!)


3

Perl 5, 18 байт

Немного похоже на Ruby (запустить perl nameofscript):

rename$0,reverse$0

Принятие во внимание возможного пути более утомительно (47 байт)

($a,$b)=$0=~/(.*\/)?(.*)/;rename$0,$a.reverse$b

1
Здравствуйте и добро пожаловать в PPCG! Отличный первый пост!
NoOneIsHere

2

V , 29 26 байт

:se ri
izyw:!mv z "
dd

Так как это содержит непечатаемые, вот шестнадцатеричный дамп:

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

Примечание: это не будет работать на v.tryitonline.net, так как TIO не разрешает доступ к файлам.

Объяснение:

: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.

2

Python 3, 105 байт

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

-Alex.A удален 1 байт.

-Цифровая травма показала мне os.rename (), который забрал 62 байта.

Грязная рыба удалила 7 байт.


Я думаю, что вы можете сохранить байт, удалив пробел после запятой вimport
Alex A.

import os,sys;f=sys.argv[0];os.rename(f,f[::-1])должен сделать трюк для 48 байтов
Digital Trauma

выполнение f [:: - 1] меняет не только имя файла, но и весь путь. Однако, спасибо, что познакомили меня с функцией os.rename ().
Пурпурный

@Magenta Для меня, sys.argv[0]просто возвращает имя файла только без пути, когда скрипт запускается самостоятельно. Хелка указала, что все в порядке
Цифровая травма

@DigitalTrauma, когда я запускал программу самостоятельно, sys.arg [0] возвращал полный путь. Я добавлю второе решение, где sys.argv [0] - это просто имя файла.
Пурпурный

2

PHP, 84, 7054 байта

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


РЕДАКТИРОВАТЬ: удалено 14 байтов благодаря insertusernamehereв комментариях
РЕДАКТИРОВАТЬ: удалено 16 байтов благодаря Martijnв комментариях


2
Вы можете получить его до 70 байт : rename($f=__FILE__,__DIR__."/".strrev(pathinfo($f)[filename]).".php");.
имя пользователя здесь

Отлично !!! но твой код лучше, вау у тебя 31 байт
tttony

Вы не можете сделать это относительным? Можно было бы сэкономить 7 байтов:rename($f=__FILE__,"./".strrev(pathinfo($f)[filename]).".php");
Мартейн

или даже меньше:rename(__FILE__,strrev(basename(__FILE__,'.php')).'.php');
Мартейн

Круто! Добавляя переменные, я получил сейчас 54 байта
tttony

2

PowerShell, 39 байт

mi *(-join((ls).name)[-5..-999]+'.ps1')

Привет и добро пожаловать в PPCG! Хороший первый пост!
Rɪᴋᴇʀ



1

Perl 6 ,  70   27 байт

Если бы ему нужно было работать в другом рабочем каталоге, вам нужно что-то вроде этого:

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

Поскольку рабочий каталог будет таким же, что и программа, его можно упростить до:

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

Объяснение:

$_ = $*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

1

JavaScript (узел), 108 104 68 байт

36 байтов сохранено, благодаря Downgoat!

Версия для Windows:

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

Другая версия:

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

@ Мне не нужно, я не думаю. Я соответствую jsв конце пути к файлу, которому предшествует символ. Это всегда будет ..
Конор О'Брайен

1

JavaScript ES6 (Node.js) 70 байт

Нет Regex Yay!

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

Любая помощь приветствуется


1

PowerShell v4 +, 68 байт

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

Работает только потому, что скрипт гарантированно находится в каталоге сам по себе. Выполняет ls(псевдоним для Get-ChildItem) и принимает .Nameрезультирующий объект (ы). Мы сохраняем это в буквальном периоде, $cа затем в -splitнем, чтобы получить имя файла и расширение, и сохраняем их в $aи $b, соответственно.

Далее это mv(псевдоним Move-Item) команды, где мы движемся $cк $a(обратный) .$b.

пример

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

1

Python (2,7 или 3,4+), 61 49 байт

Я считаю, что это близко к оптимальному решению Python:

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

Вдохновлен s4b3r6ответом, но использует срез списка вместо обратного и сохраняет __file__в переменную, чтобы сохранить байты при его двойном использовании.

Примечание. Предполагается, что имя файла всегда *.py. Несколько более универсальным решением, которое может обрабатывать любое двухсимвольное расширение файла, было бы использовать его a[-3:]для замены ".py", затратив 1 дополнительный байт.

Обновление: 12 байтов сохранены с помощью трюка среза списка, a[-4::-1]чтобы удалить расширение файла, вместо разделения, а затем с помощью реверса a.split(".")[0][::-1].


1

Powershell, 112 байт

Я не собираюсь побеждать Unix cmds, просто добавляю свои два пенса для удовольствия :-)

gci * | % { $n=($_.basename[-1..-(($_.basename).length)] -join “”)+$_.Extension; mv -Path $_.Fullname -Dest $n }

Добро пожаловать в PPCG! Мы требуем, чтобы ответы отображали их оценки, поэтому я отредактировал их для вас. Кроме того, вы можете отформатировать код, выделив его и выбрав кнопку, которая выглядит как квадратные скобки {}, или добавив 4 пробела перед кодом.
FryAmTheEggman

0

PowerShell, 50 байт

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

Файл только один, поэтому mv *подстановочный знак будет иметь только один результат. Имя назначения, в (ls).basenameкотором перечислены все файлы (псевдоним 'dir'), вызывает свойство BaseName - и поскольку существует только один файл, PowerShell распакует массив из 1 элемента в строку. Сохраните это имя в файле $f, затем индексируйте его обратным отсчетом и -joinобратные символы вернутся в строку. Добавьте обязательный .ps1суффикс.



0

Python 2.7, 68 байт

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

Это, наверное, лучшее, что я могу получить. Я просто доказал, что ошибаюсь.


0

Python (2 и 3), 88 78 байт

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

Использует тот факт, что имя файла задается sys.argv (поскольку рабочим каталогом является папка, в которой находится файл), и использует os.rename. Досадно, что перевернутый возвращает итератор, поэтому мы должны использовать соединение.

Изменить: 10 байтов были сохранены с использованием __file__ вместо sys.argv [0], как предложено @muddyfish для @DigitalTrauma.



0

Сценарий Visual Basic, 44 байта

WScript.Echo(StrReverse(WScript.ScriptName))

Пример вывода для файла с именем reverse.vbs(Run with cscript):

sbv.esrever


0

SmileBASIC 60 байт

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

Альтернатива:

P$=PRGNAME$()T$=P$*1WHILE""<T$Q$=Q$+POP(T$)WEND
RENAME P$,Q$
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.