2

I have folders with a lot of files, Each folder has txt files of the same name, I want to merge all txt files from all subdirectories into a single folder.

Example:

/home/parent/Folder1 ===> txtfile1.txt, txtfile2.txt, txtfile3.txt
/home/parent/Folder2 ===> txtfile1.txt, txtfile2.txt, txtfile3.txt
/home/parent/Folder3 ===> txtfile1.txt, txtfile2.txt, txtfile3.txt

I want to merge all files with the same name into a different folder.

/home/parent/Merged ===> txtfile1.txt, txtfile2.txt, txtfile3.txt
1
  • Is the question not specific? i have read how to ask a good question and still doesn't understand what is wrong with my question, I have search all the web about it and doesn't get a satisfied answer before asking! Commented Jan 20, 2022 at 15:03

2 Answers 2

0

You may use this:

mkdir "/home/parent/MERGED"
find "/home/parent/Folder1" -type f -name '*txt' -printf '%f\0' | 
xargs -0 -I FILENAME find "/home/parent" ! -path '/home/parent/MERGED/*' \
-type f -name FILENAME\
-exec sh -c 'cat "$1" >> "/home/parent/MERGED/$2"' sh {} FILENAME \;

What it does:

  • create target directory
  • scan FOLDER1 and print filenames (without path) followed by NUL as separator
  • read in this list with xargs
  • run find once per input name and scan parent for files with said name
  • exclude the target directory from this search
  • concatenate the resulting finds into a file in MERGED with the given name

Note: The data in the output files is not necessarily sorted by the names of FOLDER1, FOLDER2 etc. but by how find retrieves the files.

Note2: Absolute paths are a necessity for properly filtering the merged directory.

2
  • I'm getting this error when i try this ==> find: paths must precede expression: `sh' Commented Jan 20, 2022 at 15:21
  • This looks like a typo or a misplaced asterisk. Could you show the exact command as you typed it in? Do the files and/or directories have spaces in them?
    – FelixJN
    Commented Jan 20, 2022 at 15:48
0

With zsh:

cd /home/parent && mkdir -p Merged || exit
typeset -A files
for file (Folder*/*.txt(nN)) files[$file:t]+=$file$'\0'
for file (${(k)files}) cat -- ${(0)files[$file]} > Merged/$file

Note the n glob qualifier to apply a numeric sorting to the glob expansion so Folder2 comes before Folder10 and txtfile1.txt before txtfile10.txt for instance.

Note that hidden files are skipped. If you want them merged as well, add the D glob qualifier.

You must log in to answer this question.

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