Linux echo append find command output into log file - linux

I would like to know is there any way to show the message with "echo function" + "find command" output into log file?
Current:
/mnt/backup/XXXX/Daily/Logs/20210326.log
Code:
logfile=$(date +"%Y%m%d")
find /mnt/backup/XXXX/Daily/Logs -type f -name "*.log" -mtime +6 -print -exec rm {} \; >> /mnt/backup/XXXX/Daily/Logs/$logfile.log
Expected result:
Deleted file - /mnt/backup/XXXX/Daily/Logs/20210326.log
Remark: Bold text is belong to echo function. Normal text is belong to find command.

Use a second -exec and so:
find /mnt/backup/XXXX/Daily/Logs -type f -name "*.log" -mtime +6 -print -exec rm {} \; -exec echo 'Deleted file - {}' >> /mnt/backup/XXXX/Daily/Logs/$logfile.log \;

Related

Append date to the filename using find and exec comand

having the following bash code on Linux, how I can modify it to append the datestamp after gz accomplished his process?
DOMINIO=filenetvers
DATAORA_ATTUALI=$(date +"%Y.%m.%d")
GGZIP=1
GGRM=90
find /work/pr-${DOMINIO}-0[0-2]/servers -name "*.log*[^gz]" -type f -user bea -mtime +${GGZIP} -exec /usr/bin/gzip -9 -f {} "*.gz.$DATAORA_ATTUALI" \;
find /work/pr-${DOMINIO}-0[0-2]/servers -name "*.stdout*[^gz]" -type f -user bea -mtime +${GGZIP} -exec /usr/bin/gzip -9 -f {} "*.gz.$DATAORA_ATTUALI" \;
find /work/pr-${DOMINIO}-0[0-2]/servers -name "*.stderr*[^gz]" -type f -user bea -mtime +${GGZIP} -exec /usr/bin/gzip -9 -f {} "*.gz.$DATAORA_ATTUALI" \;
This to view your output from find:
find ./ -type f -name "nsshow*" -exec echo cp {} /tmp/{}_test \;
cp ./nsshow_SANSW06_FABB /tmp/./nsshow_SANSW06_FABB_test
cp ./nsshow_SANSW02_FABB /tmp/./nsshow_SANSW02_FABB_test
cp ./nsshow_SANSW05_FABA /tmp/./nsshow_SANSW05_FABA_test
cp ./nsshow_SANSW01_FABA /tmp/./nsshow_SANSW01_FABA_test
This to run it:
find ./ -type f -name "nsshow*" -exec cp {} /tmp/{}_test \;
The above "for" loop is nice and simpel for Advanced work:
for f in $(find /work/pr-${DOMINIO}-0[0-2]/servers -name "*.log*[^gz]" -type f -user bea -mtime +${GGZIP})
do
/usr/bin/gzip -9 -f $f
mv $f.gz $f.gz.$DATAORA_ATTUALI
done
A simple solution is to use a simple for loop and do the gzip and rename like this :
for f in $(find /work/pr-${DOMINIO}-0[0-2]/servers -name "*.log*[^gz]" -type f -user bea -mtime +${GGZIP}) ; do /usr/bin/gzip -9 -f $f ; mv $f.gz $f.gz.$DATAORA_ATTUALI; done

"find -type f -iname '*.txt' | xargs -I {} echo ""> {}" does not work

I am working on linux bash. Now I would like to clear the contents of all .txt files. However, this command "find -type f -iname '.txt' | xargs -I {} echo ""> {}" seems not to work. Any suggestions? Any ideas about better solutions?
I replaced echo with truncate in order to clear a file and used find's -exec instead of piping to xargs:
find . -type f -name "*.txt" -exec truncate -s 0 {} \;

Detect if a file was created with todays date and then remove older files

I have a script which deletes files older than +2 days in a specific Directory.
I would like to check if there is a file with todays date created before removing the older files.
This is what I have:
#!/bin/bash
find /var/backups/server1 -type f -mtime +2 -exec rm {} \;
find /var/backups/server2 -type f -mtime +2 -exec rm {} \;
find /var/backups/server3 -type f -mtime +2 -exec rm {} \;
find /var/backups/server4 -type f -mtime +2 -exec rm {} \;
find /var/backups/server5 -type f -mtime +2 -exec rm {} \;
So Basically:
1.Check Directory with file with todays date.
2.If affirmative find /var/backups/serverX -type f -mtime +2 -exec rm {} \;
3.If not "execute scriptX" (which maybe a mail notification)
thanks!
You could do something like this
find /var/backups/ -maxdepth 1 -type d -print0 | while read -rd '' dirname
do
arry=( $(find "${dirname}" -type f -atime 0) )
#Checks if there is a file that is updated today.
[ "${#arry[#]}" -ge 1 ] && find "${dirname}" -type f -mtime +2 -exec rm {} \;
done

List all directories that contain a file with a particular extension

I need list all the directories that contain a file with .info extension in the first level.
--contrib
--abc
--ab.info
--def
--de.info
--xyz
--ab.gh
--ab.ij
The command should list
abc, def
This should work if you run it from your contrib directory:
find . -maxdepth 2 -name "*.info" -exec dirname {} \;
It will need more tweaking if you actually want to run it from the parent of contrib.
The above will give you:
./abc
./def
Which is not exactly what you wanted. So maybe something more like this will help:
find . -maxdepth 2 -name "*.info" -exec sh -c 'F=$(dirname {}) ; basename $F' \;
It is more convoluted but the result is:
abc
def
Or without basename and dirname:
find . -maxdepth 2 -name "*.info" -exec bash -c '[[ {} =~ .*/(.*)/.* ]] && echo ${BASH_REMATCH[1]}' \;
Or with sed:
find . -maxdepth 2 -name "*.info" -exec echo {} + | sed 's|./\(\S*\)/\S*|\1,|g'
Result:
abc, def,

Using both basename and full path in find -exec

I'm having an adventure in the world of bash scripting with find today.
Say I'm looking to copy any png file in any subdirectory of /home/mine/Pictures to /home/mine/pngcoppies and rename it "copy[basename]"using find and -exec. This would require me to use both the full path name and the basename in the same exec command. My problem is that I don't know how to get the basename. (See below)
find /home/mine -iname "*.png" -exec cp {} /home/mine/pngcoppies/copy{what_do_I_enter_here?} \;
Note: The above isn't actually what I'm doing, but it's a fundamental example of the issue, so a workaround using some other method to achieve the same ends wouldn't really apply here. The question is fundamentally about find -exec and its use of basenames.
Thanks in advance!
To see what is going on when you execute the find, just type set -xv
-x : Prints commands and their arguments as they are executed.
-v : Prints shell input lines as they are read.
Here is what I have :
find . -name "*.xml" -exec echo {} \;
Gives the output:
./log.xml
./svnLog.xml
And when I try :
set -xv
find . -name "*.xml" -exec echo {} \;
I get :
find . -name "*.xml" -exec echo {} \;
+ find . -name '*.xml' -exec echo '{}' ';'
./log.xml
./svnLog.xml
And then find execute echo passing the found filename instead of the litteral : '{}'
but when you add something to the {} like below :
find . -name "*.xml" -exec echo something{} \;
+ find . -name '*.xml' -exec echo 'something{}' ';'
something{}
something{}
Here the echo is executed twice for the 2 xml files that I have and since there is no more '{}' is the parameter list of the exec, it is not going to be replaced. so we got the echo 'something{}' for each file found.
To deal with this, you can think about executing echo passing to it the filename as parameter like for example :
sh -xvc 'echo sothing/$0' filename
We already know what is -x and -v. -c is to get the command from the string after it (man sh)
so the result is :
sh -xvc 'echo somthing/$0' filename
+ sh -xvc 'echo somthing/$0' filename
echo somthing/$0
+ echo somthing/filename
sothing/filename
I used 'echo somthing/$0' between ' ' so that $0 don't get expanded by the current shell. try it with " " and you will see the expantion of $0 ;)
So to get back to your 'problem', the find should be formatted as below:
find . -name "*.xml" -exec sh -xvc 'echo sothing/$0' {} \;
And we will get :
find . -name "*.xml" -exec sh -xvc 'echo sothing/$0' {} \;
+ find . -name '*.xml' -exec sh -xvc 'echo sothing/$0' '{}' ';'
echo sothing/$0
+ echo sothing/./log.xml
sothing/./log.xml
echo sothing/$0
+ echo sothing/./svnLog.xml
sothing/./svnLog.xml
As we can see know, the find is going to execute the shell cammand echo sothing/$0 passing to it '{}' (replaced by the filename found by find) so we get the desired echo sothing/./log.xml
set +xv to remove the verbose mode
and we can get :
find . -name "*.xml" -exec sh -c 'echo "cp $0 someWhereElse/$0"' {} \;
cp ./log.xml someWhereElse/./log.xml
cp ./svnLog.xml someWhereElse/./svnLog.xml
so in your case , you have just to execute the copy in a sub shell (add sh or bash or you favorit shell after the exec) and let find pass the filename as parapeter to the it ;)
find /home/mine -iname "*.png" -exec sh -c 'cp $0 /home/mine/pngcoppies/copy/$0' {} \;
Hope this can help, and execuse me for my English.
From man find:
"The -execdir primary is identical to the -exec primary with the exception that utility will be executed from the directory that holds the current file. The filename substituted for the string ``{}'' is not qualified."
find /home/mine -iname "*.png" -execdir cp {} /home/mine/pngcoppies/copy{} \;
try something like this :
find /home/mine -iname "*.png" -printf "%P\n " | xargs -I % -n1 cp % /home/mine/pngcoppies/copy%
To get basename you use
basename $your_full_path
To get that path before the basename
dirname $your_full_path
You need to combine the first two answers
I was tailing everything in one directory into another directory with
find . -type f -exec sh -c 'tail -n 1000 $0 >../tail1000/$0.tail' {} \;
The first Answer gives
cp ./log.xml someWhereElse/./log.xml
or for my tail command
find . -type f -exec sh -c 'tail -n 1000 $0 >../tail1000/$0.tail' {} \;
tail -n 1000 ./filenane > ../tail1000/./filenane.tail
which surprisingly works but does not look like a nice path and I expect there are cases where a path/./morepath does something unexpected with some command.
Combining the answers gives
find . -type f -execdir sh -c 'tail -n 1000 $0 >../tail1000/$0.tail' {} \;
which executes
tail -n 1000 filenane > ../tail1000/filenane.tail
And looks much more likely to give the expected results.

Resources