find directory and make symbolic link into hard link in directory - linux

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

Related

How to find and rename a batch of files in 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")"' {} \;

Error find: paths must precede expression with Linux command

I am getting below error:
"find: paths must precede expression: zip"
I am trying to execute below:
cd /ohi/oraBase/Extract_Files; BACKUPFILE=OIG_EXTRACT_FILES-$(date); ERR_LOG_FILE=`echo "ODI_Readable_File.log" | cut -f 1 -d '.'`; mkdir "$BACKUPFILE"; find . -maxdepth 1 -type f -not -name "ERR_LOG_FILE".* -exec mv {} "/ohi/oraBase/Extract_Files/$BACKUPFILE" \; zip -r "$BACKUPFILE".zip "$BACKUPFILE";
Below is working fine:
cd /ohi/oraBase/Extract_Files; BACKUPFILE=OIG_EXTRACT_FILES-$(date); ERR_LOG_FILE=`echo "ODI_Readable_File.log" | cut -f 1 -d '.'`; mkdir "$BACKUPFILE"; find . -maxdepth 1 -type f -not -name "ERR_LOG_FILE".* -exec mv {} "/ohi/oraBase/Extract_Files/$BACKUPFILE" \;
Looks like below is culprit:
zip -r "$BACKUPFILE".zip "$BACKUPFILE";
If I execute each command one time, even zip is working.
why error in single line execution?
This is solved. I needed second ; after zip command zip -r "$BACKUPFILE".zip "$BACKUPFILE";
some how it was not seprating zip command with find.

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 files in multiple directories taken from list in a file?

FreeBSD 9.2 RELEASE p2
I have a file fromdirs.txt. In this file is a new line separated directory list like so:
/etc
/home
/home/goods/
I need to first find in all directory's files which have names like "good" or contain string "(NODES_'TASK')" and then copy all these files into the directory /tmp.
2.sh file chmod +x and is 755
fromDirs.txt file chmod +x and is 755
This code give me error
IFS=$'\n' read -d '' -r -a dirs < fromDirs.txt
find "${dirs[#]}" -type f \( -name '*good*' -o -exec grep -F "(NODES_'TASK')" {} \; \) -exec cp {} /tmp/ \;
2.sh: cannot open fromDirs.txt : No such file or directory
2.sh: ${dirs[...}: Bad substitution
But File fromDirs.txt exist and 2.sh running from it allocation directory, also i trying to provide full path instead of fromDirs.txt and error the same
This code give me error
FILE=fromDirs.txt
IFS='\n'
while read -r dirs
do
find "$dirs" -type f \( -name '*good*' -o -exec grep -F "(NODES_'TASK')" {} \; \) -exec cp {} /tmp/ \;
done < "$FILE"
2.sh: 6: Syntax error: "done" unexpected (expecting "do")
This code give me error too
FILENAME=fromDirs.txt
awk '{kount++;print kount, $0}
END{print "\nTotal " kount " lines read"}' $FILENAME
2.sh: : not found awk: can't open file fromDirs.txt source line number 2
So how to read file line by line and do what i need?
This works for me
for line in "`cat fromDirs.txt`"; do find "$line" -type f \( -name '*good*' -o -exec grep -F "(NODES_'TASK')" {} \; \) -exec cp {} /tmp/ \;; done

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