Как сопоставить содержимое одного файла и переименовать содержимое файлов из каталогов и подкаталогов с помощью Linux

У меня есть следующий небольшой текстовый файл ( mapfile.txt ) на моей Linux-машине. Мне нужно использовать информацию в этом файле, чтобы переименовать другие файлы в других каталогах и подкаталогах. Как я могу это сделать?

Подсказки к вопросам:

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.

Я пробовал это:

s/search/replace/g 

, но это неправильный формат.

mapfile.txt:

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

другие файлы, такие как:

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

Ожидается:

test : 0% : 0%
de_top : 0.68% : 0.99%
new_block2: 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
0
13.03.2017, 12:13
3 ответа

Сильфонное решение может применяться для замены содержимого файла (или нескольких файлов) .

Во-первых, вы можете выполнить итерацию по файлу карты следующим образом:

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

Если вы раскомментируете строку над sed, вы вызовете sed внутри цикла, используя переменные, которые вы читаете из файла карты следующим образом:
sed "s / prj1 / DCMS_DEMO / g " для первой строки файла карты
sed" s / blk1 / de_top / g " для второй строки файла карты и т. Д.

Это решение имеет ловушку: sed будет вызывается много раз, по одному разу на строку, читаемую из файла карты, поэтому производительность будет медленной.

Чтобы ускорить процесс, вы можете «создать» «сценарий замены», который может подавать sed один раз в конце. Для этого мы можем сделать что-то вроде этого внутри цикла:

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

Когда цикл завершен и весь сценарий замены sed готов, вы можете вызвать sed один раз в конце следующим образом:

sed -f replacements file1

Демонстрация со сценарием замены 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%

Советы:
Если вам нужно сделать изменения в файле file1 постоянными, используйте sed -i
Если вам нужно применить тот же сценарий sed к большему количеству файлов в каталоге, вы можете сделать это как:
sed -i -f заменяет * #or / dir / * или * .txt и т. д.

0
28.01.2020, 04:47
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 {} +

Вывод

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

Brief

find находит все файлы, начиная с текущего каталога и далее, просматривает файлы с расширениями .config и загружает их в Perl , который открывается в режим редактирования на месте -i . Сначала он генерирует хэш отображения из mapfile.txt , а затем применяет его ко всем последующим файлам в списке аргументов 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 {} +
0
28.01.2020, 04:47

With 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%
0
28.01.2020, 04:47

Теги

Похожие вопросы