How to copy recursive directories to a flat directory - linux

I am trying to copy all the *.psd files, currently in a multi directories structure, into one single directory.
Is there an rsync parametrization to allow it?
The solution proposed at Copying files from multiple directories into a single destination directory is not a multilevel recursive directories, only single level subdirectories.
In my current case I have files in multiple recursive directories (up to 7 levels) that I would like to reconcile in a single directory.

I fear rsync can't help you here. You can use find to find all the files and copy them to the destination directory, though:
find /path/to/source/topdir -type f -name '*.psd' -exec cp {} /path/to/destination/ \;

In my opinion #choroba's answer is the right one.
For completeness (or if for any reason you needed the files to be copied with rsync) you can do something way less efficient using rsync (which is just like using cp in this case), using find, a loop and other things not really necessary.
for file in $(find ./path/to/source/topdir -name "*psd" ); do rsync $file /path/to/destination/; done

Related

Copy or move all files in a directory regardles of folder depth or number

Lets say i have a folder named Pictures and I want to move or copy all files out of this folder.
However I also want to move and harvest all of the files who are in sub folders so:
Pictures/1.png
Pictures/yolo/2.png
Pictures/yolo/swag/sand/3.png
Pictures/extra/fire/4.png
I want to move or copy all these files to another folder like results so I get:
results/1.png
results/2.png
results/3.png
results/4.png
Only I have no idea in advance what sub folders will be in the Pictures folder.
How can I accomplish this in bash/shell scripts ?
I also appreciate making it file type neutral so any files are harvested from their directories (not only .png like in my example) and I have no idea what the file name will be (I only used 1...4 because i did not have any idea how to name them).
You can do it like this:
find /absolute/path/to/Pictures -type f -name '*.png' -exec mv -i {} /absolute/path/to/results \;
Another option is to use xargs
find /absolute/path/to/Pictures -name '*.png' | xargs -I files mv files /absolute/path/to/results
You can simply copy all files and subdirectories along with their contents using cp's recursive option:
cp -pr <source_path>/* <destination_path>/
But, moving them recursively is a bit tricky, you will need to create tar files of the subdirectories and move them and then untar the tar files in destination path. As this is a complex process, as a workaround, you can copy the files/directories recursively and then delete the files from original path.
cp -pr <source_path>/* <destination_path>/ && rm -rf <source_path>/*

Linux Copy All Files with specific filename length

I want to Copy all files in my directory with a specific file name length.
e.g.
These files exist:
1.py
12.py
123.py
321.py
1234.py
Than I want to copy only the files 123.py and 312.py (because of length of 3)
I am new to Linux and donĀ“t know how to accomplish this. Anyone can help me?
If I understood correctly, you want to copy files whose names consist of three characters followed by .py. This could be done using:
cp ???.py destination_directory/
(Note: this could fail if you have a very large number, but the limit is typically large on modern systems.)
You can do it using the command find
find directory1 -type f -size 3k -exec cp -nv {} directory2/ \;

Rsync make flat copy

I'm trying to write a script that copy all the files of one dir (with subdirs) to the root of another dir.
So Imagine I have this file structure:
/
pic.JPG
PIC5.JPG
FOLDER
pic2.JPG
pic3.JPG
FOLDER2
pic4.JPG
I want all the .JPG files from that directory and copy them over to another destination. But I don't want the directory structure, just the files.
This is what I've got:
"sudo rsync -aq --include '*/' --include '*.JPG' --exclude '*\' /source/picturesRoot/ /destination/flatView/
But it also copies the directories :(
I found this link on stackoverflow:
rsync : Recursively sync all files while ignoring the directory structure
I looked at the solution and didn't see much difference with my command, apart from the * and . in the path. I tried it but it didn't work.
I hope somebody can help me, thanks.
This answer cannot work for you because your pictures are not at the same level in directories. There is no option in rsync to skip the creation of directory structure. In the link you gave, it's working because the user explicitly select source files with *.
You can try something with find and rsync. Find will find files and rsync copy them.
Here is a solution :
find /source/picturesRoot -type f -name "*.JPG" -exec rsync -a {} /destination/flatView/ \;
Be careful, if two files have the same name just one will be in destination directory.

Need to touch a file in several directories using one liner in linux

I have lots of directories. I need to cd to all the directories and create 2 files. I tried doing this using xargs, but I couldn't do it. Can you please tell me how to achieve this?
If you don't want or need to run find but have a list of directories, something like this:
xargs -i touch {}/a {}/b <directories.txt
If the directory paths are completely regular (e.g. all subdirectories two levels down), it might be as easy as
touch */*/a */*/b
find <path> -type d -exec touch {}/a {}/b \;
path may be . if you are already in the top directory you are interested to work on.

Bash script to recursively step through folders and delete files

Can anyone give me a bash script or one line command i can run on linux to recursively go through each folder from the current folder and delete all files or directories starting with '._'?
Change directory to the root directory you want (or change . to the directory) and execute:
find . -name "._*" -print0 | xargs -0 rm -rf
xargs allows you to pass several parameters to a single command, so it will be faster than using the find -exec syntax. Also, you can run this once without the | to view the files it will delete, make sure it is safe.
find . -name '._*' -exec rm -Rf {} \;
I've had a similar problem a while ago (I assume you are trying to clean up a drive that was connected to a Mac which saves a lot of these files), so I wrote a simple python script which deletes these and other useless files; maybe it will be useful to you:
http://github.com/houbysoft/short/blob/master/tidy
find /path -name "._*" -exec rm -fr "{}" +;
Instead of deleting the AppleDouble files, you could merge them with the corresponding files. You can use dot_clean.
dot_clean -- Merge ._* files with corresponding native files.
For each dir, dot_clean recursively merges all ._* files with their corresponding native files according to the rules specified with the given arguments. By default, if there is an attribute on the native file that is also present in the ._ file, the most recent attribute will be used.
If no operands are given, a usage message is output. If more than one directory is given, directories are merged in the order in which they are specified.
Because dot_clean works recursively by default, use:
dot_clean <directory>
If you want to turn off the recursively merge, use -f for flat merge.
dot_clean -f <directory>
find . -name '.*' -delete
A bit shorter and perform better in case of extremely long list of files.

Resources