Powershell, элемент переименования не работает должным образом
У меня есть несколько файлов изображений JPG, названных в следующем шаблоне:
0001-rand01_012.jpg
0002-rand03_034.jpg
Я хочу переименовать их, удалив первые 5 символов, чтобы получить форму:
rand01_012.jpg
так далее..
Я использую следующую команду:
Get-ChildItem | Rename-Item -NewName {$_.name.Substring(5)}
При использовании этого с флагом -whatif я получаю ожидаемое сообщение:
Performing the operation "Rename File" on target "Item: C:\Users\xxxx\Documents\xx xx\temp2\0123-rand16_030.jpg Destination: C:\Users\
xxxx\Documents\xx xx\temp2\rand16_030.jpg".
Но удаляя whatif
дает мне ошибки этого типа:
Rename-Item : The input to the script block for parameter 'NewName' failed. Exception calling "Substring" with "1" argument(s): "startIndex cannot be
larger than length of string.
сопровождаемый целой связкой:
Rename-Item : Cannot create a file when that file already exists.
Сами файлы переименовываются с удалением случайного числа символов, а не 5, как предполагалось. Таким образом, они в конечном итоге, как:
01.jpg
01.jpg
.
.
.
d14_001.jpg
и т.п.
Я использовал эту команду для успешного переименования таких файлов в прошлом. Тот факт, что я получаю такие случайные результаты, заставляет меня вырывать волосы.
1 ответ
ТЛ; др
Убедитесь, что вы обрабатываете только интересующие вас файлы:
(Get-ChildItem -File [0-9][0-9][0-9][0-9]-*.jpg) |
Rename-Item -NewName {$_.name.Substring(5)}
размещение (...)
вокруг Get-ChildItem
не технически необходимо, но желательно. [1]
Сюда:
Вы исключаете несвязанные файлы заранее.
Даже если что-то пойдет не так, вы можете исправить проблему и снова запустить команду, чтобы обработать только сбойные файлы, не затрагивая ранее переименованные файлы.
- Наиболее вероятная причина, по которой что-то пошло не так, - более 1 входного файла, приводящего к тому же имени файла после удаления 5 первых символов.
Похоже, вы по ошибке выполнили команду несколько раз, поэтому вы отрезали 5 символов. несколько раз:
0001-rand01_01.jpg
-> rand01_01.jpg
-> _01.jpg
Если имя файла содержит менее 5 символов, вы получите startIndex
ошибка, потому что [string]
класса .Substring()
метод не принимает индекс за пределами длины строки (попробуйте 'ab'.Substring(3)
).
Тем не менее, так как вы бежите Get-ChildItem
без фильтра и, следовательно, возврата всех (не скрытых) дочерних элементов, вы можете обрабатывать несвязанные файлы или даже каталоги, имена которых слишком короткие.
Cannot create a file when that file already exists.
ошибки - это просто последующие ошибки, возникающие из блока скрипта, который обычно возвращает новое имя, фактически возвращая пустую строку, поэтому Rename-Item
несколько неясно жалуется, что вы не можете переименовать файл с его текущим именем.
Тем не менее, вы можете даже получить Cannot create a file when that file already exists
ошибки во время первого запуска, а именно, если более 1 входного файла с его первыми 5 символами. отрубил результаты в том же имени файла.
Например, 0001-rand01_012.jpg
а также 0002-rand01_012.jpg
оба будут переименованы в rand01_012.jpg
, которая завершается ошибкой после переименования первого.
То есть, чтобы ваша команда работала так, как задумано, все имена файлов, возникающие в результате удаления первых 5 символов. Должно быть уникальным.
Вот MCVE (минимальный, полный и проверяемый пример):
Настроить:
# Create and change to temp dir.
Set-Location (mkdir temp)
# Create sample input files named 0001-rand01_01.jpg, 0002-rand01_02.jpg, ...
# Note how the suffixes after the first 5 char. must be *unique*.
1..9 | %{ $null > "000${_}-rand01_0${_}.jpg" }
1-й пробег:
# No errors
> (Get-ChildItem -File) | Rename-Item -NewName { $_.Name.Substring(5) }
# Show new names
> Get-ChildItem | Select Name
Name
----
rand01_01.jpg
rand01_02.jpg
rand01_03.jpg
rand01_04.jpg
rand01_05.jpg
rand01_06.jpg
rand01_07.jpg
rand01_08.jpg
rand01_09.jpg
Второй прогон дает:
Name
----
1_01.jpg
1_02.jpg
1_03.jpg
1_04.jpg
1_05.jpg
1_06.jpg
1_07.jpg
1_08.jpg
1_09.jpg
Во время 3-го запуска все имена слишком короткие, и все, что вы получите, это Rename-Item : Cannot create a file when that file already exists.
ошибки.
[1] Вложение Get-ChildItem
в (...)
гарантирует, что соответствующие файлы собраны в массиве, перед Rename-Item
вызывается.
Это явно предотвращает повторное перечисление уже переименованных файлов Get-ChildItem
и, таким образом, мешая итерации; явное использование (...)
технически не нужно, потому что Get-ChildItem
реализован таким образом, что всегда внутренне собирает все файлы заранее, на разных платформах, потому что сортирует их по имени, что по своей сути возможно только после того, как все имена были собраны.
В свете того, используете ли вы (...)
или не должны функционально равняться, хотя использование (...)
желательно, потому что это не зависит от деталей реализации.