Correct syntax for shell script - linux

Am trying to create one and add the same to the cron.
This is the commands I am trying to run through the script.
#!/bin/bash
find . -mmin -60 -name "*.jpg" $(printf "! -name %s " $(cat processed.txt) ! -name cache) -exec convert -resize 1000x800 -quality 85% {} {};
find -mmin -60 -type f -name "*.jpg" -exec basename {} \; &> processed.txt
f I am running these commands directly on shell, I don't get any error.
but if say I have stored this in a file called compress and run the script as ./compress
I get the error -
find: missing argument to `-exec'
what mistake I am making and how I can fix that.

Build an array of arguments for the first find command instead of relying on the command substitution.
while IFS= read -r line; do
processed+=(! -name "$line")
done < processed.txt
Your immediate problem, though, is that you forgot to escape the semicolon so that it would be treated as an argument to find, rather than a command terminator.
find . -mmin -60 -name "*.jpg" "${processed[#]}" \
! -name cache -exec convert -resize 1000x800 -quality 85% {} {} \;
# ^^
find -mmin -60 -type f -name "*.jpg" -exec basename {} \; &> processed.txt

Related

I want to get an output of the find command in shell script

Am trying to write a script that finds the files that are older than 10 hours from the sub-directories that are in the "HS_client_list". And send the Output to a file "find.log".
#!/bin/bash
while IFS= read -r line; do
echo Executing cd /moveit/$line
cd /moveit/$line
#Find files less than 600 minutes old.
find $PWD -type f -iname "*.enc" -mmin +600 -execdir basename '{}' ';' | xargs ls > /home/infa91punv/find.log
done < HS_client_list
However, the script is able to cd to the folders from HS_client_list(this file contents the name of the subdirectories) but, the find command (find $PWD -type f -iname "*.enc" -mmin +600 -execdir basename '{}' ';' | xargs ls > /home/infa91punv/find.log) is not working. The Output file is empty. But when I run find $PWD -type f -iname "*.enc" -mmin +600 -execdir basename '{}' ';' | xargs ls > /home/infa91punv/find.log as a command it works and from the script it doesn't.
You are overwriting the file in each iteration.
You can use xargs to perform find on multiple directories; but you have to use an alternate delimiter to avoid having xargs populate the {} in the -execdir command.
sed 's%^%/moveit/%' HS_client_list |
xargs -I '<>' find '<>' -type f -iname "*.enc" -mmin +600 -execdir basename {} \; > /home/infa91punv/find.log
The xargs ls did not seem to perform any useful functionality, so I took it out. Generally, don't use ls in scripts.
With GNU find, you could avoid the call to an external utility, and use the -printf predicate to print just the part of the path name that you care about.
For added efficiency, you could invoke a shell to collect the arguments:
sed 's%^%/moveit/%' HS_client_list |
xargs sh -c 'find "$#" -type f -iname "*.enc" -mmin +600 -execdir basename {} \;' _ >/home/infa91punv/find.log
This will run as many directories as possible in a single find invocation.
If you want to keep your loop, the solution is to put the redirection after done. I would still factor out the cd, and take care to quote the variable interpolation.
while IFS= read -r line; do
find /moveit/"$line" -type f -iname "*.enc" -mmin +600 -execdir basename '{}' ';'
done < HS_client_list >/home/infa91punv/find.log

Problems with understanding and combining linux terminal commands

First one :
We found several files and we have to copy that to kat4 and here is code, but it doesn't seem to work corectly
find /home/imk-prac/ -type f -size -13c -name '*\?plik\?*' -exec cp {} /home/inf-19/aduda/\*kat1\*/\*kat2\*/\*kat4\*/ \; 2> /dev/null
'cp' I assume that it is copy, but I don't know what 'exec' and '{}' do.
Second one:
find /home/imk-prac/ \( -type f -size -13c -name '*\?plik\?*' \) -o\( -type d -name '\[Kolo1\]*' \)2> /dev/null
Generally,I understand this line (except for '2' and '-o') , but I want to add looking for files which were modificated in less that 30 days and here is what I wanted to combine with upper command :
find /home/imk-prac/ -type f -mtime -30 -exec ls -l {} \; > /dev/null
As a result I wrote it down as:
find /home/imk-prac/ \( -type f -size -13c -name '*\?plik\?' -mtime -30 -exec ls -l{}\) -o \( -type d -name '\[Kolo1\]*' \) 2> /dev/null
but it doesn't work
Moreover, I wanted to add looking for files with speciefied quantity of symbols and I found this command:
grep -Po '(^|\s)\S{64}(\s|$)' file
But I have no idea how to combine all of those 3 upper commands.
I will be grateful for any help, thank you for your time!

shell script that allows to empty a file when it exceeds a certain size

I'm looking for a Linux script that allows to empty the contents of a file when it exceeds a certain size for example 50 kB.
I tried this script :
#!/bin/bash
find /home/walid/Documents -type f -size +50k -exec echo >"{}" \;
but it does not work.
On the other hand it works well for deleting files:
#!/bin/bash
find /home/walid/Documents -type f -size +50k -exec rm "{}" \;
Your redirection (>) takes place before starting find. You probably now have a file of name {}.
I propose to use truncate instead of a redirection for overwriting the file:
find /home/walid/Documents -type f -size +50k -exec truncate --size 0 "{}" \;
A little tweak on your first script should work fine:
#!/bin/bash
find /home/walid/Documents -type f -size +50k -exec sh -c 'echo -n > {}' \;
Give a try to this:
find /home/walid/Documents -type f -size +50k -exec cp /dev/null {} \;
That should work in any *nix like operating system, but also you could give a try to truncate -s 0 filename
find /home/walid/Documents -type f -size +50k -exec truncate -s 0 {} \;

linux find: move files by xargs

How should this be fixed? I am following a tutorial but I receive this error:
$ find ~/Desktop -name “*.jpg” -o -name “*.gif” -o -name “*.png” -print0 | xargs -0 mv –target-directory ~/Pictures
mv: cannot stat `–target-directory': No such file or directory
*I am interested on how to perform this command using xargs!
Using find and exec
$ find ~/Desktop -name "*.jpg" -exec mv '{}' /tmp/target/ \; -or -name "*.gif" -exec mv '{}' /tmp/target/ \; -or -name "*.png" -exec mv '{}' /tmp/target/ \;
Using xargs
$ find ~/Desktop -name "*.jpg" -or -name "*.gif" -or -name "*.png" | xargs -I SRCFILE mv SRCFILE /tmp/target/
You don't need to use xargs, find can execute commands on the matches:
find ~/Desktop -name “*.jpg” -o -name “*.gif” -o -name “*.png” -exec mv \{\} ~/Pictures \;
You can give a command after -exec and before the escaped semicolon \;. The \{\} is replaced with the matching file name.
From man find:
-exec command ;
Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to the command until an argument consisting of ';' is encountered. The string '{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a '\') or quoted to protect them from expansion by the shell. See the EXAMPLES section for examples of the use of the -exec option. The specified command is run once for each matched file. The command is executed in the starting directory. There are unavoidable security problems surrounding use of the -exec action; you should use the -execdir option instead.
Notice that the semicolon and {} must be escaped.
I believe -target-directory should be --target-directory, or just -t.

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

Resources