![Найти текст в файлах и переименовать файлы в пакетном режиме](https://rvso.com/image/1638143/%D0%9D%D0%B0%D0%B9%D1%82%D0%B8%20%D1%82%D0%B5%D0%BA%D1%81%D1%82%20%D0%B2%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0%D1%85%20%D0%B8%20%D0%BF%D0%B5%D1%80%D0%B5%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D1%84%D0%B0%D0%B9%D0%BB%D1%8B%20%D0%B2%20%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BD%D0%BE%D0%BC%20%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B5.png)
У меня возникли проблемы с созданием скрипта, который находит определенный текст в каждом файле внутри папки, получает содержимое после этого текста и устанавливает его в качестве имени файла, и все это внутри цикла, чтобы выполнить то же самое для нескольких файлов.
например, у меня есть папка с файлами file1, file2, file3
content in file1: sw_part = "ABC-DEF.GHJ";
content in file2: sw_part = "ABC-123.XYZ";
content in file3: sw_part = "ABCDE-FGHJ.KLMN";
Результат должен быть:
file1 renamed to ABC-DEF.GHJ
file2 renamed to ABC-123.XYZ
file3 renamed to ABCDE-FGHJ.KLMN
Вот что я сделал:
for /F "tokens=2 delims==" %%a in ('findstr /I "sw_part" file1') do set "swpart=%%a"
echo sw part is: %swpart%
copy file1 "%swpart%"
Это работает нормально, но работает только для заданного файла (я не могу заставить это работать с циклом), а также переименовывает файл с помощью;
в конце. Есть помощь?
Это нужно сделать в пакетном режиме. PowerShell тоже подойдет.
Спасибо
решение1
Следующий скрипт сделает то, что вам нужно.
cd C:\temp\swpart
$files = [System.Collections.ArrayList]@()
select-string -Path "*.*" -Pattern "sw_part" | ForEach-Object {
$old_filename = $_.Filename
$new_filename = $_.line -replace "^.*sw_part = ""","" -replace """.*$",""
# put everything in array, so the files get closed and can be renamed later.
$null = $files.Add(@{"old"=$old_filename;"new"=$new_filename})
}
$files |ForEach-Object{
$old_filename = $_.old
$new_filename = $_.new
rename-item $old_filename $new_filename -Force
}
Обязательно измените первую строку на путь к файлам.
Если по какой-то причине не все файлы переименованы, запустите скрипт еще раз. Тогда файл все еще использовался.
решение2
- С помощью PowerShell вы также можете сделать это, используя всего две строки:
ls 'F:\2020-SU\Q1605996\*.txt'|%{$new=(cat $_.FullName).split('\"*\"')[-2];ren $_.FullName -new $new -force}
- Без использования псевдонимов:
Get-ChildItem 'F:\2020-SU\Q1605996\*.txt' | ForEach {
$new=(Get-Content $_.FullName).split('\"*\"')[-2]
Rename-Item $_.FullName -new $new -force
}
- Вы также можете сделать это с помощью cmd всего в одну строку:
В командной строке:
for /f tokens^=1-3delims^=^:^"^" %a in ('findstr . *.txt')do @ren "%~fa" "%~c"
В файле bat/cmd:
@echo off
cd /d "C:\Path\To\Your\Folder"
for /f tokens^=1-3delims^=:^"^" %%a in ('findstr . *.txt')do @ren "%%~fa" "%%~c"
Findstr
команда и вывод
>F:\Q1605996>findstr . *.txt
file1.txt:sw_part = "ABC-DEF.GHJ";
file2.txt:sw_part = "ABC-123.XYZ";
file3.txt:sw_part = "ABCDE-FGHJ.KLMN";
file4.txt:sw_part = "ABCDE-FGHJ.KXMN";more test/strings
file5.txt:this is a test; sw_part = "fea.geow.eaf.gae"; this is another test;
For
механика циклической команды
set yours delimiters : + " + " ==>> delims^=:^"^"
set yours tokens "1" - "3" ==>> tokens^=1-3
: = ;
token = 1:token =2= token = 3;
file1.txt:sw_part = "ABC-DEF.GHJ" ;
file2.txt:sw_part = "ABC-123.XYZ" ;
file3.txt:sw_part = "ABCDE-FGHJ.KLMN";
file4.txt:sw_part = "ABCDE-FGHJ.KXMN";more test/strings
| | | |
ren "%f~a" "%~c"
ren "F:\Q1605996\file1.txt" "ABC-DEF.GHJ"
ren "F:\Q1605996\file2.txt" "ABC-123.XYZ"
ren "F:\Q1605996\file3.txt" "ABCDE-FGHJ.KLMN"
ren "F:\Q1605996\file4.txt" "ABCDE-FGHJ.KXMN"
rem :: The same in file5.txt
file5.txt:this is a test;sw_part = "fea.geow.eaf.gae"; this is another test;
| | | |
ren "%f~a" "%~c"
ren "F:\Q1605996\file5.txt" "fea.geow.eaf.gae"
Дополнительные ресурсы PowerShell:
Split()
Replace()
Substring()
Rename-Item
|ren
ForEach-Object
|%
|?
Get-Content
|type
|cat
Get-ChildItem
|ls
|dir
Дополнительные ресурсы cmd/batch: