Copy files based on regex to another folder but keep folder structure - copy

I want to copy files matching a regex to another folder but while keeping part of the folder structure, All the filepaths will start with src/main/java/ buth the path before that is different for most files
I know that I can use
find . -iregex ".*HeadersConstants\.java" -exec cp {} ./destination/ \;
To copy a file but then I lose the file path in the destination dir

Are you on linux? Historically, cpio would have been an obvious choice but these days rsync is likely to be better:
find . -iregex ".*HeadersConstants\.java" |\
rsync -v --files-from=- ./ ${destination}/
It's probaby not a good idea for the destination to be inside . as your question code suggests but we can stop find looking there with:
find . -path ./destination -prune \
-o -iregex ".*HeadersConstants\.java" -print |\
rsync -v --file-from=- ./ ./destination/
(You may want to investigate why the -print is required.)

In the meantime I got it to work (probably not the cleanest way)
javaRe='(.*)\/src\/main\/java\/(.*)\/'
find . -name "HeadersConstants\.java" | while read f
do
if [[ ${f} =~ ${javaRe} ]]; then
path=${BASH_REMATCH[2]}
fullpath=${destination}${srcDir}${path}
mkdir -p "$fullpath"
cp "$f" "$fullpath"
fi
done

Related

Move files and copy subtree

source="/somedir/dir-a"
dest="/somedir2/dir-z"
I need to find all files recursively within the $source directory which contain the string 720p and move them to $dest
Just 2 things to take care of -
For all such files which are to be moved , first create that file's outer 2 directories in $dest and then move this matched file inside that
i have to do this for lakhs of files so a bit of parallelization would be helpful
Example
For a file like - "$source/dir-b/dir-c/file-720p.mp4" , it should do as follows :
mkdir -p "$dest/dir-b/dir-c"
mv "$source/dir-b/dir-c/file-720p.mp4" "$dest/dir-b/dir-c/file-720p.mp4"
You're looking for something like this:
src=foo
dst=bar
export dst
find "${src}" -name '*720p*' -type f -exec sh -c '
for p; do
np=${dst}${p#"${p%/*/*/*}"}
echo mkdir -p "${np%/*}" &&
echo mv "$p" "$np"
done' sh {} +
This can be parallelized using GNU find's -print0 primary in conjunction with GNU xargs, but I don't think that'd make much of a difference performance-wise, as this is rather an IO-intensive task.
Remove echos if the output is satisfactory.

Waring on linux cmd: find . -delete -name "*.swp"

I try to delete all .swp file which vim created with the following command:
find . -delete -name "*.swp" .
Then my whole project is deleted...
Can anyone tell me why? and how to recover the project?
if you change the command to this:
find . -name "*.swp" -delete
it'll only delete the file it match
find . -delete -name "*.swp"equals to rm -rf *
This issue is a warning message for programmer.
find predicates and actions form a boolean expression that is evaluated left to right with short-circuiting.
Your expression:
find . -delete -name "*.swp"
is equivalent to the bash expression:
rm "$file" && [[ $file == *.swp ]]
This deletes the file, and if the deletion is successful it checks the name.
Compare this to:
# Like: find . -name "*.swp" -delete
[[ $file == *.swp ]] && rm "$file"
In this case, it checks the name. If the check passes, it deletes the file. This is what you intended.
This behavior is super useful, because it allows you to write more advanced control flow and branching:
find . -name '.git' -prune \
-o \( -name '*.xz' -exec xz -d {} \; \
-o -name '*.gz' -exec gzip -d {} \; \) \
-printf 'Successfully extracted %f\n'
This expression will skip any .git directory, run xz -d on .xz files only, gzip -d on .gz files only, and finally print a message for the files that were extracted.
As for your files, they're deleted. It's often not possible to get them back. You'll have to restore them from your backup or, if you're desperate, try to follow a file un-deletion guide for your OS and filesystem (but again, it's often not possible).

Delete multiple files in CENTOS command

How can i delete all the file that are ending with *0x0.jpg in CENTOS ? I need to delete multiple files nested into folders and subfolders
I assume you have a shell - try
find /mydirectory -type f -print | grep '0x0.jpg$' | xargs -n1 rm -f
There is probable a more elegant solution but that should work
However I would put an echo in before rm on the first run to ensure that the right files are going to be removed.
Ed Heal's answer works just fine but neither the grep nor xargs calls are necessary. The following should work just as well and be a good bit more efficient for large amounts of files.
find /mydirectory -name '*0x0.jpg' -type f -exec rm -rf () \+

mv: "Directory not Empty" - how do you merge directories with `mv`?

I tried to deploy my personal blog website to my remote server recently. When I tried to move a few files and directories to another place by executing mv, some unexpected errors happened. The command line echoed "Directory not Empty". After doing some googling, I tried again with '-f' switch or '-v', the same result showed.
I logged in on the root account, and the process is here:
root#danielpan:~# shopt -s dotglob
root#danielpan:~# mv /var/www/html/wordpress/* /var/www/html
mv: cannot move `/var/www/html/wordpress/wp-content` to `/var/www/html/wp-content`:
Directory not empty
root#danielpan:~# mv -f /var/www/html/wordpress/* /var/www/html
mv: cannot move `/var/www/html/wordpress/wp-content` to `/var/www/html/wp-content`:
Directory not empty
Anybody know why?
(I'm running Ubuntu 14.04)
If You have sub-directories and "mv" is not working:
cp -R source/* destination/
rm -R source/
I found the solution finally. Because the /var/www/html/wp-content already exists, then when you try to copy /var/www/html/wordpress/wp-content there, error of Directory not Empty happens. So you need to copy /var/www/html/wordpress/wp-content/* to /var/www/html/wp-content.
Just execute this:
mv /var/www/html/wordpress/wp-content/* /var/www/html/wp-content
rmdir /var/www/html/wordpress/wp-content
rmdir /var/www/html/wordpress
Instead of copying directories by cp or rsync, I prefer
cd ${source_path}
find . -type d -exec mkdir -p ${destination_path}/{} \;
find . -type f -exec mv {} ${destination_path}/{} \;
cd $oldpwd
moves files (actually renames them) and overwrites existing ones. So it's fast enough.
But when ${source_path} contains empty subfolders you can cleanup by rm -rf ${source_path}

How to copy a file on several directories with the name *Co* (where *=wildcard)

How to copy a file to several directories of the form *Co*? or *52?
Apparently, just typing
cp fileA *Co*
won't work.
My other concern is that if a directory already contains fileA, I don't want it to be overwritten. That is, if the directory *Co* contains fileA, do NOT copy. Is there a one line solution for this, since I think writing a script with if-else is an overkill.
Thanks!
If your version of cp supports -n, you can do:
find . -name '*Co*' -exec cp -n fileA {} \;
If not:
find . -name '*Co*' -exec sh -c 'test -f $0/fileA || cp fileA $0' {} \;
Note that these will each descend recursively: if you don't want that you can limit the scope of find. To find either Co or *52, you can do:
find . \( -name '*Co*' -o -name '*52' \) -exec ...