3

I have been digging through questions but can't seem to find the exact answer I need.

I have a directory with multiple subdirectories:

sent       sent.~16~  sent.~22~  sent.~29~  sent.~35~  sent.~41~  sent.~48~  sent.~54~  sent.~60~  sent.~67~  sent.~73~  sent.~8~
sent.~10~  sent.~17~  sent.~23~  sent.~3~   sent.~36~  sent.~42~  sent.~49~  sent.~55~  sent.~61~  sent.~68~  sent.~74~  sent.~80~
sent.~11~  sent.~18~  sent.~24~  sent.~30~  sent.~37~  sent.~43~  sent.~5~   sent.~56~  sent.~62~  sent.~69~  sent.~75~  sent.~81~
sent.~12~  sent.~19~  sent.~25~  sent.~31~  sent.~38~  sent.~44~  

Where each subdirectory holds a bunch of numbered files:

1.   11.  13.  15.  17.  4.  6.  8.
10.  12.  14.  16.  3.   5.  7.  9.

Essentially I would like to merge all these subdirectories into one directory, but not overwrite files with the same name. Will I need to change the name of files in each subdirectory to do this (ex: foo --> foo_~10~), and then merge all files to one subdirectory?

Is there an easy bash or shell script I can use for this? I have tried some variations of rsync, mv, and cp, but haven't quite gotten what I would like.

1 Answer 1

2

You can do this with a script like

#!/bin/bash

mkdir merged
for dir in sent*
do
    cd "$dir"
    for file in *
    do
        mv "$file" "$file"_"${dir#sent.}"
    done
    mv * ../merged
    cd ..
done

if you want to rename each file according to the scheme in your question. If you'd like to rename them in such a way that their lexicographic order reflects in which folder the file was originally, just switch the order of the strings $file and ${dir#sent.}.

4
  • I think using <code> rsync "$dir/$file" $target/${file}_${dir} </code> would be better? The final "mv * ../merged and cd "$dir" and cd .. can be avoided
    – tpb261
    Dec 9, 2018 at 9:27
  • @tpb261 Good point. But then the inner for-loop would have to be for file in $dir/* which would require the mv-statement to be mv "$file" $target/${file#*/}_${dir#sent.} which would be uglier and would require an expansion of the variable target and the removal of the $dir/ from the file path once for every file in $dir, though this doesn't really add to the time, I guess. One the other hand, there is the mv * ../merged command in my script. I don't know what is more efficient, to be honest. Dec 9, 2018 at 15:15
  • @tpb261 By the way, isn't rsync for copying, not for moving files? Dec 9, 2018 at 15:18
  • Agreed. The mv becomes a bit lengthier (though I don't think it's ugly yet). But, yes unless measured I can't be sure which is more optimal (gut feel: looping through the files twice would be longer). BTW, ${file#$dir}_${dir#sent} should do right? Yes, rsync is for copying not moving
    – tpb261
    Dec 11, 2018 at 6:04

You must log in to answer this question.

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