How to find and rename a batch of files in linux - linux

when using the following command:
find foo/bar -type f -name '*.txt' -execdir sh -c 'mv "$0" "new_prefix_${0}"' {}\;
I get the following error:
mv: cannot move './abc.txt' to 'new_prefix_./abc.txt': No such file or directory
The './' is the problem, how can I avoid this?

find foo/bar -type f -name '*.txt' -execdir sh -c 'mv "$0" "new_prefix_$(basename "$0")"' {} \;

Related

Override copy files using -exec cp

mkdir zipFiles
find . -name '*.zip' -exec cp {} zipFiles/ \;
Error:
cp: ‘./zipFiles/status.zip’ and ‘zipFiles/status.zip’ are the same file
I tried these commands to force copy to override the existing files, but none of them works;
find . -name '*.zip' -exec cp {} zipFiles/ \;
find . -name '*.zip' -exec cp -f {} zipFiles/ \;
find . -name '*.zip' -exec cp -rf {} zipFiles/ \;
find . -name '*.zip' -exec cp {} -rf zipFiles/ \;
You don't want find to search zipFiles. One way to do that is
find . -name '*.zip' \( ! -path '*/zipFiles/*.zip' \) -exec cp {} zipFiles/ \;
To speed things up, use -exec ... + to let cp copy as many files at once as possible. Either
find . ... -exec sh -c 'cp "$#" zipFiles' _ {} +
or, if you are using GNU cp,
find . ... -exec cp -t zipFiles {} +
You can use the rsync command:
rsync SOURCE TARGET
or
rsync --force SOURCE TARGET

find directory and make symbolic link into hard link in directory

I want to find a folder in directory and change the symbolic link in these folders into hard link.
I can find all symlink with following command:
find ${DIRECTORY_0} -type d -name "${DIRECTORY_1}" -exec bash -c 'find "$0" -type l -exec echo {\} \;' {} \;
The result is list all symlink are found.
If change echo into readlink, it shows the hard link file.
find ${DIRECTORY_0} -type d -name "${DIRECTORY_1}" -exec bash -c 'find "$0" -type l -exec readlink {\} \;' {} \;
Once I try the command :
find ${DIRECTORY_1} -type l -execdir bash -c ' cp --remove-destination -fR "$(readlink {} && rm {})" {} ' \;
that can make all symlink into hard link.
but i want to merge them together, both find ${DIRECTORY_1} in ${DIRECTORY_0} and change symlink in ${DIRECTORY_1} into hard link.
My try:
find directory -type d -name "special_folder" -exec bash -c '\
for i do
find "$i" -type l -execdir bash cp --remove-destination -fvR "$(readlink {\} && rm {\})" {\} +
done' bash {} +
but show error message
/bin/cp: /bin/cp: cannot execute binary file

How to rename multiple files at once

I have lots of files, directories and sub-directories at my file system.
For example:
/path/to/file/test-poster.jpg
/anotherpath/my-poster.jpg
/tuxisthebest/ohyes/path/exm/bold-poster.jpg
I want to switch all file names from *-poster.jpg to folder.jpg
I have tried with sed and awk with no success.
little help?
You can do it with find:
find -name "*poster.jpg" -exec sh -c 'mv "$0" "${0%/*}/folder.jpg"' '{}' \;
Explanation
Here, for each filename matched, executes:
sh -c 'mv "$0" "${0%/*}/folder.jpg"' '{}'
Where '{}' is the filename passed as an argument to the command_string:
mv "$0" "${0%/*}/folder.jpg"
So, at the end, $0 will have the filename.
Finally, ${0%/*}/folder.jpg expands to the path of the old filename and adds /folder.jpg.
Example
Notice I'm replacing mv with echo
$ find -name "*poster.jpg" -exec sh -c 'echo "$0" "${0%/*}/folder.jpg"' '{}' \;
./anotherpath/my-poster.jpg ./anotherpath/folder.jpg
./path/to/file/test-poster.jpg ./path/to/file/folder.jpg
./tuxisthebest/ohyes/path/exm/bold-poster.jpg ./tuxisthebest/ohyes/path/exm/folder.jpg
Try this script, it should rename all the files as required.
for i in $(find . -name "*-poster.jpg") ; do folder=`echo $i | awk -F"-poster.jpg" {'print $1'}`; mv -iv $i $folder.folder.jpg; done
You can replace . to the directory where these files are placed in the command find . -name "*-poster.jpg" in the script. Let me know if it is working fine for you.
you can try it like
find -name '*poster*' -type f -exec sh -c 'mv "{}" "$(dirname "{}")"/folder.jpg' \;
find all files containing poster == find -name '*poster*' -type f
copy the directory path of the file and store it in a temporary variable and afterwards affix "folder.jpg" to directory path == -exec sh -c 'mv "{}" "$(dirname "{}")"/folder.jpg' \;

find command to find files and concatenate them

I am trying to find all the files of type *.gz and cat them to total.gz and I think I am quite close on this.
This is the command I am using to list all *.gzfiles:
find /home/downloaded/. -maxdepth 3 -type d \( ! -name . \) \
-exec bash -c "ls -ltr '{}' " \
How to modify it so that it will concatenate all of them and write to ~/total.gz
Directory structure under downloaded is as follows
/downloaded/wllogs/303/07252014/SysteOut.gz
/downloaded/wllogs/301/07252014/SystemOut_13.gz
/downloaded/wllogs/302/07252014/SystemOut_14.gz
Use cat in -exec and redirect output of find:
find /home/downloaded/ -type f -name '*.gz' -exec cat {} \; > output
Use echo in -exec and redirect the output:
find /home/downloaded/ -name "*.gz" -exec echo {} \; > output

Linux find folder and rename

I want to rename all .hg_gg folders in /var/www to .hg. How can I do it?
I know how to rename .hg to .hg_gg.
find /var/www -name ".hg" -exec bash -c 'mv $0 $0_gg' {} \;
but don't know how to make reverse change.
Try this:
find /var/www -name ".hg_gg" -execdir bash -c 'mv {} .hg' \;
You need to use a special syntax defined by find: {} is the placeholder for the current file name. Check the man page for that. Also it is important to use -execdir instead of -exec. execdir changes the current working directory to the folder where the found directory is located. Otherwise it would do something like this mv /var/www/.hg_gg ./.hg
You can speed up things a bit when restricting find to find folders only using -type d:
find /var/www -type d -name ".hg_gg" -execdir bash -c 'mv {} .hg' \;
Consider this find command with -execdir and -prune options:
find /var/www/ -type d -name ".hg_gg" -execdir mv '{}' '.gg' \; -prune
-execdir will execute the command in each subdirectory
-prune causes find to not descend into the current file
Not a one liner, but you could do this:
for file in `find /var/www -name ".hg_gg"`; do
mv $file `echo $file | sed 's/hg_gg$/hg/'`
done

Resources