Busque texto en archivos y luego cambie el nombre de los archivos, en lotes

Busque texto en archivos y luego cambie el nombre de los archivos, en lotes

Tengo algunos problemas para crear un script que encuentre un texto específico en cada archivo dentro de una carpeta, obtenga el contenido después de ese texto y lo establezca como nombre para el archivo, todo eso dentro de un bucle, para realizar lo mismo en varios archivos. .

Por ejemplo, tengo una carpeta con archivo1, archivo2, archivo3

content in file1: sw_part = "ABC-DEF.GHJ";
content in file2: sw_part = "ABC-123.XYZ";
content in file3: sw_part = "ABCDE-FGHJ.KLMN";

El resultado debería ser:

file1 renamed to ABC-DEF.GHJ
file2 renamed to ABC-123.XYZ
file3 renamed to ABCDE-FGHJ.KLMN

Lo que hice es esto:

for /F "tokens=2 delims==" %%a in ('findstr /I "sw_part" file1') do set "swpart=%%a"  
echo sw part is: %swpart%   
copy file1 "%swpart%"

Esto funciona bien, pero funciona sólo para un archivo determinado (no puedo hacer que funcione con un bucle) y también cambia el nombre del archivo con;al final. ¿Alguna ayuda?

Debe hacerse en BATCH. PowerShell también está bien.

Gracias

Respuesta1

El siguiente script hará lo que quieras.

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
}


Asegúrese de modificar la primera fila para cambiar a la ruta donde están los archivos.

Si por alguna razón no se cambia el nombre de todos los archivos, ejecute el script nuevamente. Entonces el archivo todavía estaba en uso.

Respuesta2

  • Con PowerShell, también puedes hacer esto usando solo dos líneas:
ls 'F:\2020-SU\Q1605996\*.txt'|%{$new=(cat $_.FullName).split('\"*\"')[-2];ren $_.FullName -new $new -force}
  • Sin utilizar alias:
Get-ChildItem 'F:\2020-SU\Q1605996\*.txt' | ForEach {
      $new=(Get-Content $_.FullName).split('\"*\"')[-2]
      Rename-Item $_.FullName -new $new -force
     }


  • También puedes hacer esto con cmd en una sola línea:

En línea de comando:

for /f tokens^=1-3delims^=^:^"^" %a in ('findstr . *.txt')do @ren "%~fa" "%~c"

En el archivo bat/cmd:

@echo off 

cd /d "C:\Path\To\Your\Folder"
for /f tokens^=1-3delims^=:^"^" %%a in ('findstr . *.txt')do @ren "%%~fa" "%%~c"

Findstrcomando y salida

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

Formecánico de comando de bucle

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"



Recursos adicionales PowerShell:

Recursos adicionales cmd/batch:

información relacionada