Como combinar o conteúdo de um arquivo e renomear o conteúdo dos arquivos de diretórios e sub-diretórios usando o linux

0

Eu tenho o seguinte arquivo de texto pequeno ( mapfile.txt ) na minha máquina Linux. Eu preciso usar as informações neste arquivo para renomear outros arquivos em outros diretórios e subdiretórios. Como posso fazer isso?

Sugestões de perguntas:

1.i need to rename the contents of the file .

2. we should match the any of  .config files in the folders and sub folders.The rename should as follows.Column 3 names in the input file should be renamed to column 2 names in the outfile.

3.Yes only the first field should be replaced.

Eu tentei isso:

s/search/replace/g 

mas não é o formato certo.

mapfile.txt:

PROJECT:DCMS_DEMO:prj1
BLOCK:de_top:blk1
BLOCK:new_block2:blk2
BLOCK:test:blk3
CHECKLIST:Block_DV:checklist1

outros arquivos da seguinte forma:

blk3 : 0% : 0%
blk1 : 0.68% : 0.99%
blk2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%

Esperado:

test : 0% : 0%
de_top : 0.68% : 0.99%
new_block2: 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
    
por find data 13.03.2017 / 09:39

3 respostas

0

com awk :

awk -F ":" -v OFS=":" 'FNR==NR{a[$3" "]=$2" ";next} $1 in a{ $1=a[$1] };1' mapfile.txt otherfile.txt

O / P:

test : 0% : 0%
de_top : 0.68% : 0.99%
new_block2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
    
por 13.03.2017 / 11:34
0

A solução abaixo pode ser aplicada para substituir o conteúdo de um arquivo (ou de mais arquivos).

Primeiro, você pode iterar através do mapfile assim:

while IFS=: read -r desc new old;do   #IFS is used to set the delimiter, : in your case
echo "description=$desc - old value:$old - to be replaced with : $new" 
#i usually apply this echo as a cross check that all field are read correctly
#more actions here like:
#sed -i "s/$old/$new/g" file1
done <mapfile

Se você descomentar acima da linha sed você chamará sed dentro do loop, usando as variáveis que você leu no mapfile da seguinte forma:
sed "s/prj1/DCMS_DEMO/g" para a primeira linha do mapfile
sed "s/blk1/de_top/g" para a segunda linha de mapfile, etc

Esta solução tem uma armadilha: o sed será chamado muitas vezes, uma vez por linha, lida a partir do mapfile e, portanto, o desempenho será lento.

Para acelerar as coisas, você pode "construir" um "script de substituição" que pode alimentar o sed uma vez no final. Para fazer isso, podemos fazer algo parecido com isso dentro do loop:

echo "s/$old/$new/g;" >>replacements

Quando o loop terminar e todo o script de substituição do sed estiver pronto, você poderá chamar o sed uma vez no final dessa forma:

sed -f replacements file1

Demonstração com script de substituição de sed

#!/bin/bash
clear
echo "Original File1"
cat file1
while IFS=: read -r desc new old;do
echo "s/$old/$new/g;" >>replacements
done <mapfile
echo && echo "Replacements for sed"
cat replacements
echo && echo "file1 replaced"
sed -f replacements file1
rm replacements

#Output:
Original File1   
blk3 : 0% : 0%   
blk1 : 0.68% : 0.99%
blk2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33% 

Replacements for sed
s/prj1/DCMS_DEMO/g; 
s/blk1/de_top/g; 
s/blk2/new_block2/g;   
s/blk3/test/g;
s/checklist1/Block_DV/g;

file1 replaced   
test : 0% : 0%   
de_top : 0.68% : 0.99%
new_block2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%

Dicas:
Se você precisar fazer alterações permanentes no arquivo1, use sed -i
Se você precisar aplicar o mesmo script sed em mais arquivos dentro de um diretório, você pode fazer como: sed -i -f replacements * #or /dir/* or *.txt etc

    
por 13.03.2017 / 12:33
0
find . -type f -name '*.config' -exec \
perl -wMstrict -Mvars='*h' -F':' -i -pale '
   BEGIN {
     local(@ARGV, $/) = shift;
     chop(local $_ = <>); print;
     %h = reverse /^[^:]+:\K(.+?):(.*)$/gm;
   }
   s//$h{$&}/ if exists $h{ (/\S+/g)[0] };
' mapfile.txt {} +

Saída

test : 0% : 0%
de_top : 0.68% : 0.99%
new_block2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%

Breve

find localiza todos os arquivos a partir do diretório atual e analisa aqueles com extensões .config e alimenta a boca em Perl , que é aberta em in-place edit -i mode. Primeiro, ele gera um hash de mapeamento do mapfile.txt e, em seguida, aplica isso a todos os arquivos subseqüentes na lista de argumentos do Perl.

find . -type f -name '*.config' -exec \
perl -F: -i -ple '$. == ++$h and $h{$F[2]} = $F[1], 1 or exists $h{(/\S+/g)[0]} and s//$h{$&}/;
$h = 0 if eof' mapfile.txt {} +
    
por 13.03.2017 / 14:50