Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

add filename to beginning of file using find and sed

Tags:

find

shell

sed

using the following I add the file name to the front of each line and send the output to a single file.

ls | while read file; do sed -e "s/^/$file/g" $file > out; done

I want to perform the same sed replacement but using a find and exec or xargs command -

find . -type f -exec sed "s/^/{}/g" {} > out +

but I get an error -

find: Only one instance of {} is supported with -exec ... +

Input files are like this -

fileA.txt

A1
A2

fileB.txt

B1
B2

desired output

fileA.txt A1
fileA.txt A2
fileB.txt B1
fileB.txt B2

I know how to do this with awk, but I'd like to do it with sed, find and exec or xargs.

like image 276
Bryan Avatar asked Oct 18 '11 19:10

Bryan


People also ask

How do you insert a first line using sed?

Use sed 's insert ( i ) option which will insert the text in the preceding line.

Does sed modify the original file?

The sed command does not edit the source file by default, but you can change this behavior by passing the -i option, which means “perform edits in-place.” This will alter the source file.


3 Answers

untested, try using xargs

find . -type f | xargs -I FILE sed "s/^/FILE/g" FILE > out
like image 82
glenn jackman Avatar answered Oct 17 '22 17:10

glenn jackman


 find . -type f |xargs awk '$0=FILENAME$0' > out

as I answered this, your "no awk" line not yet there. anyway, take a look my updated answer below:

updated based on comment

so you want to use find, exec/xargs, and sed to do it. My script needs GNU Sed, i hope you have it.

see the one liner first: (well, > out is omitted. You could add it to the end of the line. )

find . -type f | xargs -i echo {}|sed -r 's#(.\/)(.*)#cat &\|sed  "s:^:file \2 :g"#ge'

now let's take a test, see below:

kent$  head *.txt
==> a.txt <==
A1
A2

==> b.txt <==
B1
B2

kent$  find . -type f | xargs -i echo {}|sed -r 's#(.\/)(.*)#cat &\|sed  "s:^:file \2 :g"#ge'
file b.txt B1
file b.txt B2
file a.txt A1
file a.txt A2

is the result your expectation?

Short explanation

  • find ....|xargs -i echo {} nothing to explain, just print the filename per line (with leading "./")
  • then pass the filename to a sed line like sed -r 's#(.\/)(.*)# MAGIC #ge'
  • remember that in the above line, we have two groups \1: "./" and \2 "a.txt"(filename)
  • since we have e at the end of sed line, the MAGIC part would be executed as shell command.(GNU sed needed)
  • MAGIC: cat &\|sed "s:^:file \2 :g cat & is just output the file content, and pipe to another sed. do the replace (s:..:..:g)
  • finally, the execution result of MAGIC would be the Replacement of the outer sed.

the key is the 'e' of Gnu sed.

like image 42
Kent Avatar answered Oct 17 '22 16:10

Kent


Why don't you simply replace the ls in your first line with the find like this?

find . -type f | while read file; do sed -e "s|^|$file|" $file > out; done

You must only exchange the delimiter for s from / to something else not contained in your filenames. I have chosen | as an example.

like image 38
A.H. Avatar answered Oct 17 '22 16:10

A.H.