user53029
user53029

Reputation: 695

for loop output formatting: add newline with a description and space

I'm running through a list of files to cat and redirecting all of the output to a single file using a for loop. My loop works but i'm looking for a way to add a descriptor line before each file's contents is dumped and add a space before each new file entry. Here is my script.

#!/bin/bash

files=$(ls -l /home/user/*.txt | awk 'NR>=2 {print $9}')

for i in $files; do /bin/cat "$i" >> "/home/user/catfiles.txt"
done

My output looks like this:

 spawn ssh [email protected]
 run $command
 quit
 spawn ssh [email protected]
 run $command
 quit

I would like for it to look like this:

 "Description for first file here"
 spawn ssh [email protected]
 run $command
 quit
 <space>
 "Description for second file here"
 spawn ssh [email protected]
 run $command
 quit
 <space>

UPDATE: The file description name would need to vary by file using the actual file name.

"This is $file1"
"This is $file2"
 etc,etc..

Upvotes: 0

Views: 2053

Answers (3)

user4918296
user4918296

Reputation:

This will merge them as you require it:

for f in /home/user/*.txt;do
    echo "This is ${f##*/}" >> /home/user/catfiles.txt
    /bin/cat "${f}" >> /home/user/catfiles.txt
    echo >> /home/user/catfiles.txt
done

The file name is printed without its path. If you want the path printed, too, then simply replace ${f##*/} with ${f}.

Update

${variable##pattern} is called parameter substitution. Bash will search for pattern in variable and remove the longest match. In this case the variable is f and pattern is */ which matches any String that ends with a slash. The double hash ## indicates to remove the longest String in f that can be matched by */. Since f is a path it will match and remove everything up to and including the last /, thus leaving only the filename. The Bash documentation has further and more detailed info on this subject. Alternatively, you can search in man bash for Parameter Expansion.

Upvotes: 2

Krzysztof Krasoń
Krzysztof Krasoń

Reputation: 27486

So you want this, and BTW your files=$(ls -l /home/user/*.txt | awk 'NR>=2 {print $9}') is wrong, don't parse ls output, jus use shell:

for i in /home/user/*.txt; do
    echo "Description for first file here $i" >> /home/user/catfiles.txt
    /bin/cat "$i" >> "/home/user/catfiles.txt"
    echo >> /home/user/catfiles.txt
done

Upvotes: 1

user53029
user53029

Reputation: 695

This will resolve the issue:

for i in /home/user/*; do
echo "This is from $i" >> "/home/user/catfiles.txt"
/bin/cat "$i" >> "/home/user/catfiles.txt"
    echo >> "/home/user/catfiles.txt"
done

Since "i" represents each file in this case, $i in the second line starting with echo will give you the different filename.

If you want to exclude the file path so the line simply has the file name without the /home/user you can insert a sed statement after the 3rd line.

for i in /home/user/*; do
echo "This is from $i" >> "/home/user/catfiles.txt"
/bin/cat "$i" >> "/home/user/catfiles.txt"
/bin/sed -i -e 's/\/home\/user\///g' /home/user/catfiles.txt
    echo >> "/home/user/catfiles.txt"
done

Upvotes: 0

Related Questions