Domanda

Ho il seguente script che prende in un file di input, file di output e sostituisce la stringa nel file di input con qualche altra stringa e scrive fuori il file di output.

Voglio cambiare lo script per attraversare attraverso una directory di file cioè anziché chiedere file di input e di output, lo script dovrebbe prendere come argomento un percorso di directory ad esempio C: \ temp \ allFilesTobeReplaced \ e cercare una stringa di x e sostituirla con y per tutti i file sotto che percorso di directory e scrivere gli stessi file.

Come posso fare questo?

Grazie.

$file=$ARGV[0];

open(INFO,$file);
@lines=<INFO>;
print @lines;

open(INFO,">c:/filelist.txt");

foreach $file (@lines){
   #print "$file\n";
   print INFO "$file";
}

#print "Input file name: ";
#chomp($infilename = <STDIN>);

if ($ARGV[0]){
   $file= $ARGV[0]
}

print "Output file name: ";
chomp($outfilename = <STDIN>);
print "Search string: ";
chomp($search = <STDIN>);
print "Replacement string: ";
chomp($replace = <STDIN>);

open(INFO,$file);
@lines=<INFO>;
open(OUT,">$outfilename") || die "cannot create $outfilename: $!";

foreach $file (@lines){    
    # read a line from file IN into $_
    s/$search/$replace/g; # change the lines
    print OUT $_; # print that line to file OUT
}
close(IN);
close(OUT);
È stato utile?

Soluzione

L'uso del Perl singolo rivestimento

perl -pi -e 's/original string/new string/' filename

può essere combinato con File::Find, per dare il seguente script singola (questo è un modello che uso per molte di queste operazioni).

use File::Find;

# search for files down a directory hierarchy ('.' taken for this example)
find(\&wanted, ".");

sub wanted
{
    if (-f $_)
    {
        # for the files we are interested in call edit_file().
        edit_file($_);
    }
}

sub edit_file
{
    my ($filename) = @_;

    # you can re-create the one-liner above by localizing @ARGV as the list of
    # files the <> will process, and localizing $^I as the name of the backup file.
    local (@ARGV) = ($filename);
    local($^I) = '.bak';

    while (<>)
    {
        s/original string/new string/g;
    }
    continue
    {
        print;
    }
}

Altri suggerimenti

Si può fare questo con il parametro -i:

Basta elaborare tutti i file come normale, ma includono -i.bak:

#!/usr/bin/perl -i.bak

while ( <> ) {
   s/before/after/;
   print;
}

Questo dovrebbe elaborare ogni file, e rinominare l'originale per original.bak E naturalmente si può fare come un one-liner come detto da @Jamie Cook

Prova questo

#!/usr/bin/perl -w

@files = <*>;
foreach $file (@files) {
  print $file . '\n';
}

Date anche un'occhiata al glob in Perl:

So che è possibile utilizzare un semplice Perl one-liner dalla riga di comando, dove nomefile può essere un singolo nome di file o un elenco di nomi di file. Probabilmente si potrebbe combinare questo con la risposta di BGY per ottenere l'effetto desiderato:

perl -pi -e 's/original string/new string/' filename

E io so che è banale, ma questo suona un po 'come sed, se è possibile utilizzare gli strumenti GNU:

for i in `find ./allFilesTobeReplaced`; do sed -i s/original string/new string/g $i; done

perl -pi -e '# VECCHIO # NEW # g s' il nome del file. È possibile sostituire il nome del file con il modello che soddisfa il vostro elenco di file.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top