find: missing argument to -exec in bash script - bash

The following works fine when I type it exactly in the command line:
find /<some_path>/{epson,epson_laser,epson_inkjet} -iname "*.ppd"
-exec grep "\*ModelName\:" {} \; | sed 's/.*\"\(.*\)\"/\1/'
However, when I try to call the following from a
bash script I get find: missing argument to -exec'.
I have also tried the following (in many variants):
eval find "$1" -iname "*.ppd" -exec 'bash -c grep "\*ModelName\:" "$1" | sed "s/.*\"\(.*\)\"/\1/" \;
as was mentioned in find-exec-echo-missing-argument-to-exec.
How can I get to work first code not only in terminal, but also in bash script?
P.S.: I've used eval only for expanding string "/<some_path>/{epson,epson_laser,epson_inkjet}" to multiple paths. Does anyone know better solution for doing this?

If you want to execute multiple commands over the output of find, just use the -exec options as many times required:
find -exec command1 "{}" \; -exec command2 "{}" \;
You can also define the conditions to execute an option:
find \( -exec command1 \; -false -o -exec command2 \; \)
In your case, you need something like this:
find /<some_path>/{epson,epson_laser,epson_inkjet} -iname "*.ppd" -exec grep "\*ModelName\:" "{}" \; sed 's/.*\"\(.*\)\"/\1/' "{}" \;

Related

I used the'-print0' option to handle filenames with spaces, but I get an error

#!/bin/bash
find /home/data -name '*QQ*' -print0 -exec bash -c ' mv $1 ${0/\-QQ/-TT}' {} \;
I used the'-print0' option to handle filenames with spaces, but I get an error
/home/data/gone to sea.1080p-QQ.mp4mv: target 'sea.1080p-TT.mp4' is not a directory
Which part is wrong?
Thanks
You don't need -print0, since you're not piping the output to another program.
You just need to quote properly in the bash command.
find /home/data -name '*-QQ*' -exec bash -c 'mv "$1" "${1/\-QQ/-TT}"' {} {} \;
This should work as long as the filenames don't contain double quote or $ characters.
You could also avoid bash -c by using the rename command:
find /home/data -name '*-QQ*' -exec rename 's/-QQ/-TT/' {} +

find: missing argument to `-exec`

I'm trying to get my Shell script working, but I keep getting: find: missing argument to '-exec'
#!/bin/sh
echo Hello World
find ./public_html/var/session/ -type f -name "sess*" -mtime +30 -exec rm -f {} \;
echo DONE
I've been trying to find help in these solutions but sadly none of them have solved my problem.Shell script - find: missing argument to `-exec' find: missing argument to -exec
Another option not involving -exec is to pipe the result to xargs and then rm on it:
find ./public_html/var/session/ -type f -name "sess*" -mtime +30 | xargs rm -f
man xargs
Note:
xargs supports executing in parallel with -P command, see man page.

linux find more than one -exec

find . -iname "*.txt" -exec program '{}' \; | sed 's/Value= //'
-"program" returns a different value for each file, and the output is prefixed with "Value= "
In this time the output will be "Value= 128" and the after sed just 128.
How can I take just the value "128" and have the input file be renamed to 128.txt
but also have this find run thought multiple files.
sorry for bad descriptions.
I will try to clear if needed
First write a shell script capable of renaming an argument:
mv "$1" "$(program "$1" | sed "s/Value= //").txt"
Then embed that script in your find command:
find . -iname "*.txt" \
-exec sh -c 'mv "$1" "$(program "$1" | sed "s/Value= //").txt"' _ {} \;

Is there way to use If condition inside a find command with option exec?

scenario: There are multiple files in an folder, I'm trying to find specific set of files and if a given file has specific info then I need to grep the information.
Ex:
find /abc/test \( -type f -name 'tst*.txt' -mtime -1 \) -exec grep -Po '(?<type1).*(?=type1|(?<=type2).*(?=type2)' {} \;
I need to include if condition along with find -exec (if grep is true then print the above)
if grep -q 'case=1' <filename>; then
grep -Po '(?<type1).*(?=type1|(?<=type2).*(?=type2)'
fi
Thanks
You can use -exec in find as a condition -- the file matches if the command returns a successful exit code. So you can write:
find /abc/test -type f -name 'tst*.txt' -mtime -1 -exec grep -q 'case=1' {} \; -exec grep -Po '(?<type1).*(?=type1|(?<=type2).*(?=type2)' {} \;
Tests in find are evaluated left-to-right, so the second grep will only be executed if the first one was successful.
If your conditions are more complicated, you can put the whole shell code into a script, and execute the script with -exec. E.g. put this in myscript.sh:
#!/bin/sh
if grep -q 'case=1' "$1"; then
grep -Po '(?<type1).*(?=type1|(?<=type2).*(?=type2)' "$1";
fi
and then do:
find /abc/test -type f -name 'tst*.txt' -mtime -1 -exec ./myscript.sh {} \;
Since you're using PCRE option -P in grep you can combine both searches into one grep as well using lookahead:
find /abc/test -type f -name 'tst*.txt' -mtime -1 -exec grep -Po '(?=.*case=1).*\K((?<=type1).*(?=type1)|(?<=type2).*(?=type2))' {} +
btw the regex shown in your question is invalid, that I've tried to correct it here.

integrate sed into find xargs copy shell command

I have a script that I use to copy all of the files in one folder and move them to a new folder... the line i use to do it looks like this
find "$SOURCEFOLDER" -type f | xargs -I {} ln {} "$ENDFOLDER/$TR_NEW_TORRENT_NAME/${basename}"
and it works perfectly
the thing is I'd like to also use sed to remove any brackets from the basename of the new file but i don't know how to incorporate the sed command
sed -e 's/\[[^][]*\]//g' FILE
how would I go about doing this? Is there a better or simpler way to do all the things I want?
I believe following will work for you:
find "$SOURCEFOLDER" -type f -exec bash -c "sed -e 's/\[[^][]*\]//g' {} ; xargs -I {} ln {} "$ENDFOLDER/$TR_NEW_TORRENT_NAME/${basename}" \;
Idea is to combine the commands this ways:
another way is to use two -exec
find "$SOURCEFOLDER" -type f -exec sed -e 's/\[[^][]*\]//g' {}\; -exec ln {} "$ENDFOLDER/$TR_NEW_TORRENT_NAME/${basename}" \;
I hope this will help.
You can use -execdir option of find for this renaming and avoid xargs altogether:
find "$SOURCEFOLDER" -type f -execdir bash -c 'sed "s/\[[^][]*\]//g" <<< "$1";
ln "$1" "$ENDFOLDER/$TR_NEW_TORRENT_NAME/${basename}"' - '{}' \;

Resources