0

I have the following small text file (mapfile.txt) on my Linux machine. I need to use the information in this file to rename other files in other directories and subdirectories. How can I do this?

Question Hints:

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.

I tried this:

s/search/replace/g 

but it isn't the right format.

mapfile.txt:

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

other files as follows:

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

Expected:

test : 0% : 0%
de_top : 0.68% : 0.99%
new_block2: 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
4
  • You could do one sed script to parse the mapfile, generating a scipt to be used for the other files, but there are reason to prefer an all-in-one solution. So, if you know some script language like python or perl, you may want to use that. If you still prefer sed along with shell script, please post your try and we'll help you along.
    – Philippos
    Mar 13, 2017 at 9:12
  • Please edit your question and i) clarify whether you want to rename the files or change their contents; ii) explain how to get from your input to your expected output. It looks like mapfile has three fields, defined by : and you want the 3d field to replace the 1st field in the target file. Is that correct? iii) explain how we can find the target file. You said there are many files in different subdirectories.
    – terdon
    Mar 13, 2017 at 10:00
  • i had edited my part of code@terdon
    – find data
    Mar 13, 2017 at 10:14
  • What means "other files as follows:"? The blk3 : 0% : 0% is a filename? You need to rename filenames or you need to replace contents inside files? Is still unclear to me Mar 13, 2017 at 10:29

3 Answers 3

0

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

Bellow solution can be applied to replace contents of a file (or of more files).

First, you can itterate through the mapfile like this:

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

If you uncomment above sed line you will call sed inside the loop, using the variables that you read from mapfile like this :
sed "s/prj1/DCMS_DEMO/g" for the first line of mapfile
sed "s/blk1/de_top/g" for the second line of mapfile, etc

This solution has a pitfall: sed will be called many times, one time per line read from mapfile and thus performance will be slow.

To speed things up you can "built" a "replacement script" that can feed sed one time at the end. To do so we can do something like this inside the loop:

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

When the loop is finish and the whole sed replacement script is ready, you can call sed one time at the end like this:

sed -f replacements file1

Demo with sed replacement script

#!/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%

Tips:
If you need to make changes permanent on file1 use sed -i
If you need to apply the same sed script in more files insid a directory you can do it like :
sed -i -f replacements * #or /dir/* or *.txt etc

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 {} +

Output

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 finds all files starting from the current directory onwards and looks at those with extensions .config and feeds a mouthful to Perl which opens in in-place edit -i mode. It first generates a mapping hash from the mapfile.txt and then applies this to all the subsequent files in the Perl's argument list.

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 {} +
2
  • this is shell script or linux terminal command@Rakesh
    – find data
    Mar 14, 2017 at 6:47
  • It can be used either way.
    – user218374
    Mar 14, 2017 at 8:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .