Change the default cursor position of find-grep command in emacs - bash

I changed default find-grep command
(helped by this answer).
my init.el is following.
(grep-apply-setting 'grep-find-command "find . -type d \\( -name '.git' \\) -prune -o -type f -exec grep -nH -e \\{\\} +")
and then I execute find-grep, I get minibuffer and cursor is at end of line.
I want to change default cursor position to after -e
find . -type d \( -name '.git' \) -prune -o -type f -exec grep -nH -e (*here*) \{\} +
is this possible?
thanks.

Change the code in your init.el to the following:
(grep-apply-setting 'grep-find-command '("find . -type d \\( -name '.git' \\) -prune -o -type f -exec grep -nH -e \\{\\} +" . 72))

Related

find -print0 with 2 files only shows 1

As an example, I have two files in my directory:video.mp4 and video.webm
If I use:
find . -maxdepth 1 -type f -iname "*.mp4" -o -iname "*.webm"
I got correctly:
/video.webm
./video.mp4
But if I add -print0, that I need to pipe to parallel I got:
./video.webm
What I'm doing wrong?
Assuming your print0 attempt looks like:
find . -maxdepth 1 -type f -iname "*.mp4" -o -iname "*.webm" -print0
The -print0 is processed with the 2nd -iname option, in effect:
find . -maxdepth 1 -type f -iname "*.mp4" -o ( -iname "*.webm" -print0)
One option would be to add explicit parens to insure the -print0 is applied against both -iname options, eg:
find . -maxdepth 1 -type f \( -iname "*.mp4" -o -iname "*.webm" \) -print0

Find and replace with sed in directory and sub directories except few directories

I want to replace foo with bar in a directory structure but I want to skip few folders
I am using this command:
find ./ -type f -exec sed -i -e 's/foo/bar/g' {} \;
You -prune to skip directory:
find . -type f -o \
\( \( -name unwanted-dir1 -o -name unwanted-dir2 \) -prune -false \) \
-exec sed -i -e 's/foo/bar/g' {} \;
... or use -path ./path/to/your-dir instead of -name unwanted-dir if you want to match full path of the unwanted directory...
find . -type f -o \
\( \( -name unwanted-dir1 -o -name unwanted-dir2 \) -prune -false \) \
-exec sed -i -e 's/foo/bar/g' {} \;
This is not working because it's equivalent to
find . -type f -o \
\( \( -name unwanted-dir1 -o -name unwanted-dir2 \) -prune -false \) -and \
-exec sed -i -e 's/foo/bar/g' {} \;
since -and is assumed where the operator is omitted and -and has higher precedence than -o, so the -exec is never evaluated.
It works if the -type test is inside the outer parentheses:
find . \( -type f -o \
\( -name unwanted-dir1 -o -name unwanted-dir2 \) -prune -false \) \
-exec sed -i -e 's/foo/bar/g' {} \;
or, with fewer parentheses:
find . \( -name unwanted-dir1 -o -name unwanted-dir2 \) -prune -o \
-type f -exec sed -i -e 's/foo/bar/g' {} \;
or without parentheses as David C. Rankin suggested in his comment.

Bash - find and remove all html files but a selected ones

I'd like to do is delete all the html files recursively, omitting template.html and list.html?
So far I have the following code but I don't know how set these 2 file name exceptions.
find . -name "*.html" -exec rm -rf {} \;
You can do it with !
find . -type f \( -iname "*.html" ! -iname "template.html" ! -iname "list.html" \) -exec rm -rf {} \;
Use -not:
find . -name "*.html" -not -name template.html -not -name list.html -exec rm -rf {} \;
Try the following:
find . -type f -iname \*.html ! -iname template.html ! -iname list.html -exec rm -f -- {} +

Why wont -exec run?

I am using the below script as a clean up script. The find sections returns the correct results, but for some reason the -exec section doesn't run.
find /users/rhysparker/downloads/ -maxdepth 1 -iname \*.pkg -o -iname \*.app -o -iname \*.dmg -exec mv {} /folder/location/ \;
Any help would be appreciated.
The -o operation has low precedence, so your -exec is bound exclusively to the *.dmg test. Use parentheses to group the statement properly. (And quote them so the shell passes them through to find).
find /users/rhysparker/downloads/ -maxdepth 1 \( -iname \*.pkg -o -iname \*.app -o -iname \*.dmg \) -exec mv {} /folder/location/ \;
In expr1 -o expr2, if expr1 is true, the expr2 will not be evaluated.
In your command:
-iname \*.pkg OR
-iname \*.app OR
-iname \*.dmg AND -exec mv {} /folder/location/ \;
If one of the first two is true, the last will not be evaluated. So you have to use () to change the expr:
find /users/rhysparker/downloads/ -maxdepth 1 \( -iname \*.pkg -o -iname \*.app -o -iname \*.dmg \) -exec mv {} /folder/location/ \;
Now, it becomes:
(-iname \*.pkg OR -iname \*.app OR -iname \*.dmg) AND
-exec mv {} /folder/location/ \;
This ensure the -exec will be evaluated when the files is found.

bash: How to delimit strings to find files

What syntax should I use in a bash script to list files based on 3 dynamic values:
- older than X days
- in a specified directory
- whose name contains a specified string?
FILEAGE=7
FILEDIR='"/home/ecom/tmp"'
FILESTRING='"search-results-*"'
FILES_FOR_REMOVAL=$("/usr/bin/find "${FILEDIR}" -maxdepth 1 -type f -mtime +${FILEAGE} -name "${FILESTRING}" -exec ls -lth {} \;")
echo ${FILES_FOR_REMOVAL}
If I try the above I get:
-bash: /usr/bin/find "/home/ecom/tmp" -maxdepth 1 -type f -mtime +7 -name "search-results-*" -exec ls -lth {} \;: No such file or directory
Remove superfluous quotes:
FILEAGE=7
FILEDIR='/home/ecom/tmp'
FILESTRING='search-results-*'
FILES_FOR_REMOVAL=$(/usr/bin/find "${FILEDIR}" -maxdepth 1 -type f -mtime +${FILEAGE} -name "${FILESTRING}" -exec ls -lth {} \;)
Your syntax for 'find' looks ok. Try removing the quotes around the command string, i.e.
FILES_FOR_REMOVAL=$(/usr/bin/find "${FILEDIR}" -maxdepth 1 -type f -mtime +${FILEAGE} -name "${FILESTRING}" -exec ls -lth {} \;)
FILEAGE=7
FILEDIR='/home/ecom/tmp'
FILESTRING='search-results-*'
/usr/bin/find "${FILEDIR}" -maxdepth 1 -type f -mtime +${FILEAGE} -name "${FILESTRING}" -exec /bin/ls -lth '{}' \;
There were some extra quotes that created the error. Also specify full path to /bin/ls to avoid problems with potential aliasing of ls(1). And to get filenames on a separate line, I dropped the $FILES_FOR_REMOVAL variable. You can also use
/usr/bin/find "${FILEDIR}" -maxdepth 1 -type f -mtime +${FILEAGE} -name "${FILESTRING}" -ls
(I can't add comments, but ... )
To reliably handle file names with spaces, you may want to consider storing the file list in a temp text file instead of a variable and loop through it using a while construct (instead of a for)
For example:
FILEAGE=7
FILEDIR='/home/ecom/tmp'
FILESTRING='search-results-*'
TEMPFILE=".temp${RANDOM}"
CMD="find \"${FILEDIR}\" -maxdepth 1 -type f -mtime +${FILEAGE} -name \"${FILESTRING}\" -exec /bin/ls -lth '{}' \;"
$CMD > $TEMPFILE # write output to file
while read thefile; do
do_somthing_to $thefile
done < $TEMPFILE
rm $TEMPFILE # clean up after
Or, if you're only going to use the list once, pipe the output directly to the while construct:
$CMD | while read thefile; do
do_something_to $thefile
done

Resources