0

This is easier to explain with an example. Imagine I have a directory structure as follows:

pics/cats/png/01.png
pics/cats/png/02.png
pics/cats/jpg/01.jpg
pics/cats/jpg/02.jpg
pics/dogs/png/01.png
pics/dogs/png/02.png
pics/dogs/jpg/01.jpg
pics/dogs/jpg/02.jpg

I would like to rsync the "pics" directory to a destination, but on the destination I would like the following result, assuming the filter string for my leaf directories is "png":

pics/cats/png/01.png
pics/cats/png/02.png
pics/dogs/png/01.png
pics/dogs/png/02.png

In addition, I would like to accomplish the following result as well: (as the png dirs are no longer necessary)

pics/cats/01.png
pics/cats/02.png
pics/dogs/01.png
pics/dogs/02.png

It might be important to note that any directory might have the string "png" in it, but I only want to "filter" on the leaf directories, ie, directories that do not contain another directory.

It might be important to note also that I want to keep the contents of the "png" directories, even if they contain non-png files. Ie:

pics/cats/png/01.png
pics/cats/png/02.txt
pics/cats/jpg/01.jpg
pics/cats/jpg/02.jpg
pics/dogs/png/01.txt
pics/dogs/png/02.png
pics/dogs/jpg/01.jpg
pics/dogs/jpg/02.jpg

Becomes:

pics/cats/png/01.png
pics/cats/png/02.txt
pics/dogs/png/01.txt
pics/dogs/png/02.png

Or:

pics/cats/01.png
pics/cats/02.txt
pics/dogs/01.txt
pics/dogs/02.png

Last item to note: The directory structure might be "n" deep. Ie:

pics/cats/house/tabby/png/01.png
pics/cats/house/tabby/png/02.txt
pics/cats/house/tabby/jpg/01.jpg
pics/cats/house/tabby/jpg/02.jpg

Becomes:

pics/cats/house/tabby/png/01.png
pics/cats/house/tabby/png/02.txt

Or:

pics/cats/house/tabby/01.png
pics/cats/house/tabby/02.txt

If no easy way exists I'm sure I can just write a bash script to do it, but this seems like a use case that while not common, I'm sure crops up every now and then, and perhaps there is a name and flag for this operation.

0

You can get all the leaf nodes, filter them with grep and save the result to a file.

Then you run rsync with the --files-from option.

That is just the basics. You could filter directly in awk and/or pipe directly to to xargs for example. I'm not trying to be concise or performant, but to show the steps involved.

If you are at the root of the hierarchy:

$ find . -type d | sort | awk '$0 !~ last "/" {print last} {last=$0} END {print last}' | grep '/png$' > /tmp/dirs_rsync.txt

$ rsync -av --files-from=/tmp/dirs_rsync.txt . /your/destination/folder
| improve this answer | |
  • 1
    Does anybody care to explain the downvotes? Is there something wrong with the answer? – Eduardo Trápani Aug 12 at 4:43
  • Thank you! This works perfectly. (FWIW I upvoted also) – cat pants Aug 12 at 5:33

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.