0

I am trying to collect text files from multiple subdirectories and concatenate them into a single file per subdirectory. There may be a much better way of doing this but my question is, how does one call multiple cat commands from a bash script? Here is an example:

#!/bin/bash
cat "./directory_1/"*.txt > "directory_1.txt"
cat "./directory_2/"*.txt > "directory_2.txt"

If I keep all the commands on the same line, seperated by semicolons, it works. For example:

#!/bin/bash
cat "./directory_1/"*.txt > "directory_1.txt";cat "./directory_2/"*.txt > "directory_2.txt"

But if I need to call say 20 directories, the script becomes very hard to read.

I expected the first example to run each cat command, however, the following error was thrown:

line 2: $'\r': command not found
: No such file or directorydirectory2.txt

It looks like I have a problem with the newline character. I am trying to run this command on the Ubuntu shell for Windows 10.

3

The following loop would process every directory under the current directory in the way that you describe:

for dir in */; do
    cat "$dir"/*.txt >"${dir%/}.txt"
done

The ${dir%/} thing removes the trailing / from $dir which is there from the glob match in the loop header.

The error that you get is likely due to writing the script on a Windows machine (with a Windows editor). Windows (and DOS) text files has a carriage return character before the linefeed character at the end of every line, while Unix text files only has the linefeed character. You can convert the script to a Unix text file using the dos2unix utility.

  • This is exactly the kind of answer I was looking for. Thank you. – Nathan Apr 26 at 17:04
1

The error message is spot on in this case. The script was being saved with Windows style line endings "CR/LF" instead of Unix style "LF." Updating the line endings of the bash file fixed the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.