Переименование файлов в каталоге со списком в текстовом файле - PullRequest
1 голос
/ 22 марта 2020

У меня есть папка с тысячами файлов, и у меня нет списка имен этих файлов. Они просто случайные.

asd.wav
faf.wav
gwa.wav

И у меня есть FileNames.txt с именами файлов:

1A
2
3
4B

Я просто хочу переименовать мои файлы в порядке имен файлов в текстовый файл. Количество строк в тексте может быть больше или меньше. Он должен просто перестать переименовывать, когда дело доходит до конца строк. Как это сделать?

Ответы [ 4 ]

2 голосов
/ 22 марта 2020

Я разработал другой сценарий PowerShell:

В текущем рабочем каталоге ./ мы создаем сценарий с именем ./renamedir1.ps1. И у нас есть подкаталог ./subdir2handle, и новый список имен файлов находится в файле ./fileslist.txt.

Такое расположение может избежать влияния на файлы renamedir1.ps1 и fileslist.txt.

renamedir1.ps1 здесь:

#
# define some vars:
#
$myDir2Handle = "subdir2handle"
$myFilesList = "fileslist.txt"

#
# get files list in dir subdir2handle:
#
$xarr = (Get-ChildItem $myDir2Handle).name
$nx = $xarr.length

#
# get list file content in another array:
#
$yarr = Get-Content $myFilesList
$ny = $yarr.length
#$yarr[0]
#exit(0);

#
# get minimum of the 2 lengths:
#
$nMin = [math]::min($nx, $ny)

#
# rename items:
#
for($i = 0; $i -lt $nMin; $i++) {
    Write-Host Rename $xarr[$i]
    Move-Item ($myDir2Handle + "/" + $xarr[$i]) ($myDir2Handle + "/" + $yarr[$i])
}

В Windows мы вызываем скрипт:

.\renamedir1.ps1
2 голосов
/ 23 марта 2020

Вот ответ bash:

ls  | paste - FileNames.txt   | awk 'NF == 2 { print "mv ", $1, $2 } ' | bash

Если честно, решение немного опасно - пробелы в именах файлов (в FileNames.txt или в каталоге) будут вызывать проблемы.

Вот более надежная версия, которая обрабатывает пробелы и даже имена файлов с помощью $:

awk ' 
  FNR == NR { filename[ ++count ] = $0 ;  next }
  count > 0 { printf( "mv '"'%s' '%s'"'\n", $0, filename[ count-- ])  } 
' FileNames.txt <( ls )  | bash
2 голосов
/ 22 марта 2020

Решения PowerShell:

Решение PowerShell 7+ :

[Linq.Enumerable]::Zip(
  [string[]] (Get-ChildItem . -File).FullName,
  [string[]] (Get-Content FileNames.txt) 
) | Rename-Item -LiteralPath { $_.Item1 } -NewName { $_.Item2 } -WhatIf 

Примечание: -WhatIf общий параметр in команда выше предварительно просматривает операцию. Удалите -WhatIf, как только вы убедитесь, что операция выполнит то, что вы хотите.

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

Метод System.Linq.Enumerable.Zip позволяет удобно перечислять пар элементов коллекции в виде двухэлементных кортежей; обратите внимание, что аргументы должны быть явно введены с помощью приведений ([string[]]), чтобы PowerShell правильно разрешал вызов метода; в общем, обратите внимание, что в PowerShell, начиная с 7.0, отсутствует поддержка. NET методов расширения (что требует явного использования [System.Linq.Enumerable] здесь) и всесторонняя поддержка для вызова generi c методов , хотя на GitHub есть запросы к функциям - см. здесь и здесь .

Эти кортежи переданы в Rename-Item, чьи параметры связаны через блоки сценариев с задержкой привязки для динамического доступа к свойствам каждого входного кортежа.


PowerShell 6- решение:

# Read the array of lines == new file names from FileNames.txt
$names = Get-Content FileNames.txt

# Get as many files as new file names; '.' targets the current directory;
# Adapt as needed.
$files = (Get-ChildItem . -File)[0..($names.Count-1)] 

# Perform the renaming.
$i = 0
$files | Rename-Item -NewName { $names[$script:i++] } -WhatIf 

Примечание: переменная $i упоминается как $script:i в блоке сценария с задержкой привязки ({ ... }), поскольку блок сценария выполняется в области действия child . Чтобы это также работало в тех случаях, когда родительская область не является областью действия сценария, используйте (Get-Variable -Scope 1 i).Value++ вместо $script:i++.

0 голосов
/ 24 марта 2020

вот как я это сделал:

$FileNo = 0
$date = (get-date).ToString('yyyyMMdd')
Get-ChildItem -LiteralPath 'C:\YourFilePath\' -File | ForEach-Object {
        $_ | Rename-Item -NewName { "something" + $date + "_" + $FileNo + ($_.Extension) }
        $FileNo++
    }

для счетчика вы можете прочитать файл / csv и добавить счетчик для перехода по строкам (вы также можете пропустить дату, это просто что-то я добавил)

...