Переименуйте возвраты “bareword не позволенный” при попытке строчным частям нескольких имен файлов

У меня есть два файла в папке на моей Ubuntu 16.04:

a1.dat
b1.DAT

Я хочу переименовать b1.DAT кому: b1.dat таким образом, у меня были бы следующие файлы в результате в папке:

a1.dat
b1.dat

Я попробовал (неудачно):

$ rename *.DAT *.dat
Bareword "b1" not allowed while "strict subs" in use at (user-supplied code).
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).

и

$ find . -iname "*.DAT" -exec rename DAT dat '{}' \;
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).

Поиск этого не привел ни к какому значимому решению...

10
задан 17 March 2018 в 01:31

4 ответа

Та ошибка похожа на него, прибывает из Perl rename. Необходимо использовать заключение в кавычки, но только необходимо указать часть, которую Вы хотите изменить, стиль поиска-и-замены. Синтаксис похож на это:

rename -n 's/\.DAT/\.dat/' *

Удалить -n после тестирования для фактического переименования файлов.

Для включения скрытых файлов измените настройки шарика прежде, чем выполнить команду:

shopt -s dotglob

Если Вы хотите переименовать файлы рекурсивно, можно использовать

shopt -s globstar
rename -n 's/\.DAT/\.dat/' **

или если существует много путей в или ниже текущего каталога, которые не заканчиваются .DAT, необходимо указать те пути во второй команде:

rename -n 's/\.DAT/\.dat/' **/*.DAT

Это будет быстрее, если Ваши файлы будут иметь всевозможные имена, не заканчивающиеся в .DAT. [1]

Для выключения этих настроек, можно использовать shopt -u, например, shopt -u globstar, но они прочь по умолчанию и будут выключены, когда Вы открываете новую оболочку.

Если это приводит к чрезмерно длинному списку аргументов, можно использовать, например, find:

find -type f -name "*.DAT" -exec rename -n -- 's/\.DAT/\.dat/' {} \;

или лучше

find -type f -name "*.DAT" -exec rename -n -- 's/\.DAT/\.dat/' {} +

Используя find ... -exec с + быстрее, чем использование \; потому что это создает список аргументов из найденных файлов. Первоначально я думал, что для Вас не будет возможно использовать его, потому что Вы упомянули, что имели argument list too long проблема, но теперь я знаю, что список будет также умно поврежден в несколько вызовов команды по мере необходимости для предотвращения той проблемы [2].

С тех пор rename обработает каждое имя файла таким же образом, не имеет значения, какой длины список аргументов - поскольку это может быть безопасно разделено через несколько вызовов. Если команда Вы используете с -exec не принимает несколько аргументов или требует, чтобы его аргументы, чтобы быть в особом порядке или по любой другой причине, разделяющей список аргументов, заставили что-то нежелательное происходить, можно использовать \;, который заставляет команду быть вызванной однажды для каждого найденного файла (если список аргументов был слишком длинным для других методов, это займет много времени!).


Большое спасибо Eliah Kagan для очень полезных предложений для улучшения этого ответа:

[1] Определение имен файлов, когда globbing.
[2] find ... -exec с + разделяет список аргументов.

12
ответ дан 23 November 2019 в 04:21

Можно сделать:

rename -n 's/DAT$/\L$&/' *.DAT

Отбрасывание -n чтобы фактическое переименование произошло.

  • шаблон шарика *.DAT матчи все файлы заканчиваются в .DAT в текущем каталоге

  • в renameзамена, DAT$ соответствия DAT в конце

  • \L$& делает целое соответствие печатавшим строчными литерами; $& относится к целому соответствию

Если Вы просто хотите сделать для b1.DAT:

rename -n 's/DAT$/\L$&/' b1.DAT

Пример:

% rename -n 's/DAT$/\L$&/' *.DAT
rename(b1.DAT, b1.dat)
6
ответ дан 23 November 2019 в 04:21

Другое ответы обратились к одному из двух главных аспектов этого вопроса: это из того, как успешно провести операцию переименования, в которой Вы нуждались. Цель этого ответа состоит в том, чтобы объяснить, почему Ваши команды не работали, включая значение этого странного "bareword не позволенный" сообщение об ошибке в контексте rename команда.

Первый раздел этого ответа об отношениях между rename и Perl и как rename использует первый параметр командной строки, Вы передаете его, который является его аргументом кода. Второй раздел о том, как оболочка выполняет расширения - конкретно globbing - для построения списка аргументов. Третий раздел о том, что продолжается в коде Perl, который дает "Bareword, не разрешенному" ошибки. Наконец, четвертый раздел является сводкой всех шагов, которые происходят между вводом команды и получением ошибки.

1. Когда rename дает Вам странные сообщения об ошибках, добавьте "Perl" к своему поиску.

В Debian и Ubuntu, rename команда является сценарием Perl, который выполняет переименование файла. На более старых выпусках - включая 14.04 LTS, который все еще поддерживается с этой записи - это была символьная ссылка, указывающая (косвенно) на prename команда. На более новых выпусках это указывает вместо этого на более новое file-rename команда. Те два Perl переименовывает работу команд главным образом тот же путь, и я просто обращусь к ним обоим как rename для остальной части этого ответа.

Когда Вы используете rename команда, Вы только выполняете код Perl, который кто-то еще написал. Вы также пишете свой собственный код Perl и сообщение rename выполнять его. Это вызвано тем, что первый параметр командной строки Вы передаете rename команда, кроме аргументов опции как -n, состоит из фактического кода Perl. rename команда использует этот код для работы на каждый из путей, что Вы передаете его как последующие параметры командной строки. (Если Вы не передаете аргументов пути, затем rename пути чтений от стандартного входа вместо этого, один на строку.)

Код выполняется в цикле, который выполняет итерации однажды на путь. Наверху каждого повторения цикла, перед Вашими выполнениями кода, специальным предложением $_ переменной присваивают путь, в настоящее время обрабатываемый. Если Ваш код вызывает значение $_ чтобы быть измененным на что-то еще, затем тот файл переименован, чтобы иметь новое имя.

Много выражений в Perl воздействуют неявно на $_ переменная, когда им не дают никакое другое выражение для использования в качестве операнда. Например, выражение замены $str =~ s/foo/bar/ изменяет первое вхождение foo в строке, сохраненной $str переменная к bar, или оставляет его без изменений, если это не содержит foo. Если Вы просто пишете s/foo/bar/ явно не используя =~ оператор, затем это воздействует на $_. Это должно сказать это s/foo/bar/ коротко для $_ =~ s/foo/bar/.

Распространено передать s/// выражение к rename как аргумент кода (т.е. первый параметр командной строки), но Вы не имеете к. Можно дать ему любой код Perl, который Вы хотите для него выполнить в цикле, исследовать каждое значение $_ и (условно) измените его.

Это имеет много прохладных и полезных последствий, но подавляющее большинство их далеко за пределами объема этого вопроса и ответа. Главная причина я поднимаю это здесь - на самом деле, главная причина, я решил отправить этот ответ - состоит в том, чтобы высказать мнение что, потому что первый аргумент rename на самом деле код Perl, каждый раз, когда Вы получаете странное сообщение об ошибке, и Вы испытываете затруднения при нахождении информации об этом путем поиска, можно добавить "Perl" к строке поиска (или даже заменить, "переименовывают" с "Perl", иногда), и Вы будете часто находить ответ.

2. С rename *.DAT *.dat, rename управляйте никогда не видел *.DAT!

Команда как rename s/foo/bar/ *.txt обычно не передает *.txt как параметр командной строки к rename программа, и Вы не хотите это к, если у Вас нет файла, имя которого буквально *.txt, который, надо надеяться, Вы не делаете.

rename не интерпретирует шаблоны шарика как *.txt, *.DAT, *.dat, x*, *y, или * при передаче ему как аргументы пути. Вместо этого Ваша оболочка выполняет расширение пути на них (который также называют расширением имени файла и также называют globbing). Это происходит перед rename утилита выполняется. Оболочка разворачивает шарики в потенциально несколько путей и передает их всех, как отдельные параметры командной строки, к rename. В Ubuntu Ваша интерактивная оболочка является Bash, если Вы не изменили его, который является, почему я связался в справочник Bash выше.

Существует одна ситуация, куда шаблон шарика может быть передан как единственный нерасширенный параметр командной строки rename: когда это не соответствует никаким файлам. Различные оболочки показывают другое поведение по умолчанию в этой ситуации, но поведение Bash по умолчанию состоит в том, чтобы просто передать шарик буквально. Однако Вы редко хотите это! Если бы Вы действительно хотели это, то необходимо удостовериться, что шаблон не расширен путем заключения в кавычки его. Это идет для передающих аргументов любой команде, не только к rename.

Заключение в кавычки не только для globbing (расширение имени файла), потому что существуют другие расширения, в которые Ваша оболочка работает на неупомянутом тексте и, для некоторых из них, но не других, также на тексте, включенном " " кавычки. В целом, каждый раз, когда Вы хотите передать аргумент, который содержит символы, которые может рассматривать особенно оболочка, включая пробелы, необходимо заключить ее в кавычки, предпочтительно с ' ' кавычки.

Код Perl s/foo/bar/ не содержит ничего рассматриваемого особенно оболочкой, но это была бы хорошая идея для меня заключить это в кавычки также - и записать 's/foo/bar/'. (На самом деле единственная причина, которую я не сделал, состояла в том, что это будет сбивать с толку некоторых читателей, поскольку я еще не говорил о заключении в кавычки.) Причина я говорю, что это было бы хорошо, то, потому что очень распространено, что код Perl действительно содержит такие символы, и если бы я должен был изменить тот код, то я не мог бы помнить проверять, было ли заключение в кавычки необходимо. Напротив, если Вы хотите, чтобы оболочка развернула шарик, она не должна быть заключена в кавычки.

3. Под чем интерпретатор Perl подразумевает "bareword не позволенный"

Сообщения об ошибках, которые Вы показали в своем вопросе, показывают это, когда Вы работали rename *.DAT *.dat, Ваша оболочка расширена *.DAT в список одних или нескольких имен файлов, и что первые из тех имен файлов были b1.DAT. Все последующие аргументы - оба любых других, расширенных от *.DAT и любой расширился от *.dat- прибыл после того аргумента, таким образом, они будут интерпретированы как пути.

Поскольку то, что на самом деле работало, было чем-то как rename b1.DAT ..., и потому что rename рассматривает его первый аргумент неопции как код Perl, вопрос становится: почему делает b1.DAT произведите их "bareword не позволенный" ошибки при выполнении его как кода Perl?

Bareword "b1" not allowed while "strict subs" in use at (user-supplied code).
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).

В оболочке мы заключаем наши строки в кавычки для защиты их от непреднамеренных расширений оболочки, которые иначе преобразовали бы их в другие строки автоматически (см. раздел выше). Оболочки являются языками программирования особого назначения, которые работают совершенно по-другому по сравнению с языками общего назначения (и их очень странный синтаксис и семантика отражают это). Но Perl является языком программирования общего назначения и, как большинство языков программирования общего назначения, основная цель заключить в кавычки в Perl не состоит в том, чтобы защитить строки, но упоминать их вообще. Это - на самом деле способ, которым большинство языков программирования подобно естественному языку. На английском и предположении у Вас есть собака, "Ваша собака" является фразой с двумя словами, в то время как Ваша собака является собакой. Точно так же в Perl, '$foo' строка, в то время как $foo что-то, имя которого $foo.

Однако в отличие от примерно любого языка программирования общего назначения, Perl будет также иногда интерпретировать закрывший кавычки текст как упоминание строки - строка, которая является "тем же" как им, в том смысле, что это составлено из тех же символов в том же порядке. Это только попытается интерпретировать код тот путь, если это будет bareword (нет $ или другой символ, посмотрите ниже), и после того, как он не мог найти никакое другое значение дать его. Затем это возьмет его в качестве строки, если Вы не скажете это не путем включения ограничений.

Переменные в Perl обычно начинаются с символа акцентирования, названного символом, который указывает широкий тип переменной. Например, $ скаляр средств, @ массив средств, и % хеш средств. (Существуют другие.) Не волнуются, находите ли Вы это сбивающим с толку (или скучный), потому что я только поднимаю его, чтобы сказать что, когда допустимое имя появляется в программе Perl, но не предшествуется символом, что имя, как говорят, является bareword.

Barewords служат различным целям, но они обычно показывают встроенную функцию или пользовательскую подпрограмму, которая была определена в программе (или в модуле, используемом программой). Perl не имеет никаких названных встроенных функций b1 или DAT, таким образом, когда интерпретатор Perl видит код b1.DAT, это пытается рассматривать b1 и DAT как названия подпрограмм. Принятие никаких таких подпрограмм было определено, это перестало работать. Затем если ограничения не были включены, это рассматривает их как строки. Это будет работать, хотя, предназначили ли Вы на самом деле, это для случая является чьим-либо предположением. Perl . оператор связывает строки, таким образом, b1.DAT оценивает к строке b1DAT. Таким образом, b1.DAT плохой путь состоит в том, чтобы записать что-то как 'b1' . 'DAT' или "b1" . "DAT".

Можно протестировать это сами путем выполнения команды perl -E 'say b1.DAT', который передает короткий сценарий Perl say b1.DAT к интерпретатору Perl, который выполняет его, печатая b1DAT. (В той команде, ' ' кавычки говорят оболочке передавать say b1.DAT как единственный параметр командной строки; иначе пространство вызвало бы say и b1.DAT быть проанализированным как отдельные слова и perl получил бы их как отдельные аргументы. perl не видит сами кавычки, поскольку оболочка удаляет их.)

Но теперь, попытайтесь писать use strict; в сценарии Perl прежде say. Теперь это перестало работать с тем же видом ошибки, от которой Вы добрались rename:

$ perl -E 'use strict; say b1.DAT'
Bareword "b1" not allowed while "strict subs" in use at -e line 1.
Bareword "DAT" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.

Это произошло потому что use strict; мешавший интерпретатор Perl рассматривать barewords как строки. Для запрещения этой конкретной функции действительно было бы достаточно включить просто subs ограничение. Эта команда производит те же ошибки как выше:

perl -E 'use strict "subs"; say b1.DAT'

Но обычно программисты Perl будут просто писать use strict;, который включает subs ограничение и два других. use strict; обычно методические рекомендации. Так rename команда делает это для Вашего кода. Именно поэтому Вы получаете то сообщение об ошибке.

4. Таким образом, это - то, что произошло:

  1. Ваша оболочка передается b1.DAT как первый параметр командной строки, который rename рассматриваемый как Perl кодируют для выполнения в цикле за каждым аргументом пути.
  2. Это было взято для значения b1 и DAT соединенный с . оператор.
  3. b1 и DAT не были снабжены префиксом символы, таким образом, их рассматривали как barewords.
  4. Те два barewords были бы взяты в качестве названий встроенных функций или любых пользовательских подпрограмм, но никакая такая вещь не имела ни одно из тех имен.
  5. Если бы "строгие нижние индексы" не были включены, то их рассматривали бы как строковые выражения 'b1' и 'DAT'и связанный. Это далеко от того, что Вы предназначили, который освещает, как эта функция часто не полезна.
  6. Но "строгие нижние индексы" был включен, потому что rename включает все ограничения (vars, refs, и subs). Поэтому Вы получили ошибку вместо этого.
  7. rename выход из-за этой ошибки. Поскольку этот вид ошибки произошел рано, никакие попытки переименования файла не были предприняты, даже при том, что Вы не передали -n. Это - хорошая вещь, которая часто защищает пользователей от неумышленных изменений имени файла и иногда даже от фактической потери данных.

Спасибо переходит к Zanna, который помог мне обратиться к нескольким важным недостаткам в ealier проекте этого ответа. Без нее этот ответ сделал бы путь меньшим смыслом и не мог бы быть отправлен вообще.

3
ответ дан 23 November 2019 в 04:21

У меня была такая же ошибка. Итак, я приземлился здесь, увидел вещи, к которым можно привыкнуть, если вы новичок в среде Linux.

Я просто хочу, чтобы короткая команда легче запоминалась:

mv Greetings Greetings.java

И все. Команда mv переименовывает файл с Greetings в Greetings.java

Больше нет файла Greetings. Только файл Greetings.java готов к компиляции с использованием javac.

0
ответ дан 19 January 2021 в 06:15

Другие вопросы по тегам:

Похожие вопросы: