New answers tagged

0

Another option - feed words one at a time to xargs for it to run grep against the file. xargs can itself be made to exit as soon as an invocation of grep returns failure by returning 255 to it (check the xargs documentation). Of course the spawning of shells and forking involved in this solution will likely slow it down significantly printf '%s\n' one two ...


1

Of all the solutions proposed so far, my original solution using grep is the fastest one, finishing in 25 seconds. It's drawback is that it's tedious to add and remove keywords. So I came up with a script (dubbed multi) that simulates the behavior, but allows to change the syntax: #!/bin/bash # Usage: multi [z]grep PATTERNS -- FILES command=$1 # first ...


0

Do piping of the result [Sato] find | | cut -c -80 or find ... \ | sed 's/^\(.\{80\}\).*/\1/' or find - \ | perl -lpe 's/^.{80}\K.*//' which give correct outputs.


1

One way to do it: find . -type l -name 'Math*' -print0 | \ xargs -0 sh -c \ 'find -L "$@" -type f -name "*.tex" -exec fgrep word /dev/null {} +' sh The sh -c '...' sh abomination is necessary to deal with the case when Math* can have spaces. Otherwise, when Math* doesn't expand to filenames with spaces, something like this would work: find -L $(find ...


2

I think this must be one of the silliest command piplines I ever have concocted: $ find . -type l -name "Math*" -print0 | xargs -0 -n 1 -IXXX find XXX/ -type f -name "*.tex" -print0 | xargs -0 fgrep "word" Find all symbolic links called Math*. Do find again on each found path, looking for *.tex files. The xargs need to use -n 1 to call find with no ...


3

For compressed files, you could loop over each file and decompress first. Then, with a slightly modified version of the other answers, you can do: for f in *; do zcat -f "$f" | perl -ln00e '/one/&&/two/&&/three/ && exit(0); }{ exit(1)' && printf '%s\n' "$f" done The Perl script will exit with 0 status (success)...


7

Set record separator to . so that awk will treat whole file as a one line: awk -v RS='.' '/one/&&/two/&&/three/{print FILENAME}' * Similarly with perl: perl -ln00e '/one/&&/two/&&/three/ && print $ARGV' *


11

awk 'FNR == 1 { f1=f2=f3=0; }; /one/ { f1++ }; /two/ { f2++ }; /three/ { f3++ }; f1 && f2 && f3 { print FILENAME; nextfile; }' * If you want to automatically handle gzipped files, either run this in a loop with zcat (slow and inefficient because you'll be forking awk many times in a loop, once ...


0

To List all PNG and JPEG files which are 7 days old with absolute path. $ find $PWD/ -mtime -7 -print -exec grep -e ".png\|.jpg" {} \; Here $PWD will be added to every file matched.


5

Because when you use just *net* (without any quoting or escaping), it will be expanded by the shell as the (existing) net file/directory in the current directory before the find command run. So the command becomes: find . -name net As you can see it is just matching net, so usbnet.ko will not be matched. Also note that, without quoting and escaping, if ...


1

I don't think find has an option like this, you could build a command using printf and your exclude list: find . -name "*.txt" $(printf "! -name %s " $(cat file.txt)) -mtime +60 -exec rm -f {} + file.txt will have list of files to exclude in find command.


2

Assuming your files have sane names (i.e. they don't have embedded newlines), something like this should work: find . -mtime +60 | fgrep -v -x -f exceptions.txt | xargs -d '\n' rm -f Replace rm -f with ls -1 for a dry run first. Put paths exactly as they are printed by find in exceptions.txt.


1

Unorthodox approach: zsh -c 'echo $PWD/**/*.gz(.om[1])' where () after *.gz means to use so called glob qualifiers, i.e.: . consider only plain files om sort by modification time [1] take only first element Obviusly if you are already using zsh you don't need to call it with zsh -c.


1

You can do that by using this command, find "$(pwd)" -type f -name "*.gz" -printf "%T@ %p\n"| sort -n | cut -d' ' -f 2 | tail -n 1


1

Your understanding of -name is correct. It only matches the file name; the path leading to the file (the chain of containing directories) is irrelevant. What you're missing is the effect of -prune. Contrast find . -name ".git" -o -print which means “if it's called .git, then do nothing, else print the path and recurse into it if it's a directory” with ...


1

To ignore the .git directories and everything underneath them you need a construct like this find . \( -name '.git' -prune \) -o \( -print {or whatever else you want to do} \) This tells find that when it finds a file or directory called .git it's to prune its tree and not descend any further down that path. Everything else can be matched - and processed -...


2

The find command allows you to limit what files are matched. You can then call your script with the exec option e.g. find . \( -name '*.mp3' -o -name '*.avi' \) -exec /path/to/your/script.sh Now your script will be called for each mp3/avi file in the tree. A simple test to show this would be to have script.sh read something like #!/bin/bash echo ...


2

You can do this with find alone using the -exec action: find /location -size 1033c -exec cat {} + {} will be expanded to the files found and + will enable us to read as many arguments as possible per invocation of cat, as cat can take multiple arguments. If your find does not have the + extension or you want to read the files one by one: find /location -...


3

Your command $ find . -name 'segment*' | xargs -n1 -P4 sh someFunction.sh has the effect that at most four copies of the someFunction.sh shell script will be started (-P 4) in parallel (new ones will be spawed as soon as the old ones are done), each one getting one filename as its argument (-n 1). This means that each invocation of your script will look ...


2

You could use something like this assuming someFunction.sh is in your working directory. find . -name 'segment*' -print0| xargs -0 -n1 -P4 ./someFunction.sh The -print0 and -0 allow for files with spaces in the name (A common problem). In my someFunction.sh I have #!/bin/bash echo "Arg: " $1 cat $1 Which simply echo's out the file name then ...


3

You can also take advantage of the fact that the shell strips newlines from command substitutions. So, instead of find $PWD -type f -name "file.txt" > paths.txt, you can do (note that you don't need the $PWD, it is the default value for find): echo $(find $PWD -type f -name "file.txt") > paths.txt or printf '%s ' $(find $PWD -type f -name "file.txt"...


7

One more way, assuming GNU find(1), just for fun: find $PWD -type f -name "file.txt" -printf '%p '


4

You can use, paste too, find . -type f -name "path.txt" -exec paste -d' ' -s {} \; > path.txt


4

One simple way would be to pipe the find output through xargs (whose default action when no explicit command is given is to echo its arguments) find $PWD -type f -name "file.txt" | xargs > paths.txt Unlike simply replacing all the newlines with spaces, this preserves the final newline.


5

You can replace the LF character with a space using the 'tr' command tr '\012' ' ' < path.txt This can be part of the original command: find $PWD -type f -name "file.txt" | tr '\012' ' ' > paths.txt


1

The gzip command requires the r flag. find /a/b/c -mindepth 1 -maxdepth 1 -type d ! -name '*STDF*' -exec sh -c 'tar -zcvf "${1}".tar.gz "$@"' _ {} \;


1

you can try find /where/to/look/ -type d -not -name STDF to find the folder now that you mentioned the error you get I see you are using gzip for compressing a folder, and you can't do that. look at this answer for more information about how to compress a folder


4

The -print action does have a value of true but only after it prints. Observe that this prints all the files twice: $ find . -print -print . . ./file1 ./file1 ./file2 ./file2 Despite having two print statements, this command only prints once: $ find . \( -not -print \) -print . ./file1 ./file2 Here, the first -print evaluates to true so -not -print ...


1

Run this first to make sure it gets the desired dir's find ${DIR_LOG} -type d -mtime +90 -name "20[0-1][0-9][0-9][0-9][0-9][0-9]" then run this to actually delete them. find ${DIR_LOG} -type d -mtime +90 -name "20[0-1][0-9][0-9][0-9][0-9][0-9]" -exec rm -Rf {} \;


1

perl -l0 -ne 'print for /\\subimport\{\}\{(.*?)\}/g' file.tex Would print the filenames inside those \subimport{}{...} functions NUL-delimited. You can pipe that to xargs -0 grep -l gastric -- to find which of those files contain gastric.


0

In the end, I use the search in directory by the script here with a redirection to Vim. It would be great to get something like that work in Geany IDE directly.


2

print0 and xargs -r 0 are useless here, find has that capability builtin: [ -d /my-directory ] && find /my-directory -type f -mtime +14 -exec rm {} + or, as you are using GNU find, this variant suggested by @terdon: [ -d /my-directory ] && find /my-directory -type f -mtime +14 -delete


9

You can throw away error reporting from find with 2>/dev/null, or you can avoid running the command at all: test -d /my-directory && find /my-directory -type f -mtime +14 -print0 | xargs -r0 rm As a slight optimisation and clearer code, some versions of find - including yours - can perform the rm for you directly: test -d /my/directory &&...


2

You can use, find /my-directory -type f -mtime +14 -print0 2>/dev/null | xargs -r0 rm Explaination: 2> /dev/null means redirects stderr to /dev/null. /dev/null is the null device it takes any input you want and throws it away. It can be used to suppress any output.


1

Those files and directories do not belong to you, they belong to the root user, and have too restrictive access permissions for find and grep to work. Therefore, find complains about not being able to enter the directory /home/masi/.dbus (to do its job), and grep complains about not being able to read the files (to do its job). The files and directories do ...


2

You should be able to use -execdir to make a copy relative to the directory of the found file(s) e.g. find Italy -name '*.front.*' -execdir cp -- {} 'fanart.jpg' \; Example: given $ tree Italy/ Italy/ ├── Florence │   ├── photo.back.001.jpg │   ├── photo.back.002.jpg │   ├── photo.back.003.jpg │   ├── photo.front.001.jpg │   ├── photo.front.002.jpg │   └─...


0

Do you have a requirement to use find? For things like that, I find loops to be more appropriate: $ cd /home/user/Pictures/Vacation/Italy $ for directory in *; do \ cd "$directory" && \ for file in *front*; do \ cp --force "$file" fanart.jpg; \ done; \ cd /home/user/Pictures/Vacation/Italy; \ done Essentially, this just ...


3

Use the exec command of find: find . -name someFile.java -exec javac {} \;


2

You want to use the $() syntax. eg javac $(find ./someDir/anotherDir/ -name someFile.java)


0

To find all *BETA directories that have new files in them (-mtime -1) and save those directories names in list.txt, try: find -type f -path '*BETA/*' -mtime -1 | sed 's|^\./||; s|BETA/.*|BETA|' | sort -u >list.txt Since your goal is to create newline-separated data in the file list.txt, that must mean that you do not expect any of the directories or ...


1

Edited as the user needs: cat document.tex | cut -d'{' -f3 | cut -d'}' -f1 | while read file grep -i 'gastric' "$file" &>/dev/null && echo "$file contains gastric" done


3

pdfunite $(sed 's/$/_*.pdf/' filenames.txt) output.pdf So if filenames.txt contains CSAI_isotig00407:342-556 CSAI_isotig00408:342-556 That command will effectively do pdfunite CSAI_isotig00407:342-556_*.pdf CSAI_isotig00408:342-556_*.pdf output.pdf


0

Thanks for all the quick answers. Sorry for the extra spaces in the path, but removing them turns the path into something odd when trying to post here. I wanted to use sed for grep is really, really slow on more than 1.2 gB, 25,000 files. I've found an answer. A first sed command to chop the files with "'= chars, and then a second sed command to print the ...


1

Using your same find command, this will return the URLs that match the regex: find . -path "*alder/ * / * .html" -exec grep -oh "http://[^'\"]*" {} + Unlike find...-print | xargs command..., this approach will work on files whose names contain whitespace or other difficult characters The -o option to grep tells it to return only the matching part, not ...


-1

You may substitute the command ‍‍ls with stat -c "%n %y" , then you will get only last modify date info


0

Do the following: $ dir=/app/psoft/pscfg/appserv/prcs/ABC/LOGS $ outdir=/app/Custom_Del_logs $ find $dir -type f -mtime +45 -ls >> ${outdir}/prcslogs_$(date +%Y%m%d_%H%M).log


2

Two possible solutions that spring to mind. 1. Iterate across all the directories in LOREM and symlink them to $HOME cd "$HOME/LOREM" for item in * do test -d "$item" || continue mv -f "$HOME/$item" "$HOME/$item.DELETE_ME_LATER" 2>/dev/null ln -s "$HOME/LOREM/$item" "$HOME/$item" done # Once you are happy that only the correct files have ...


0

Please do not shame users. The {} simply takes the results of the find command (prior to the exec) and applies them to the exec portion. So what will happen is that find will find files (bigger than +50000k) and do an ls -l on them. The rest of the command line (the grep and the sort) are filtering (grep) and sorting (sort) the output.


0

You was close to solution: find /media/d/ -type f -size +50M -and ! -name "*deb" -and ! -name "*vmdk" You can combine following logic operators in any sequence: -a -and - operator AND -o -or - operator OR ! - operator NOT


2

I recently wrote an example of stuffing a shell one-liner into a find command, and this is another use case for the same. Instead of: find samples \( -iname '*.wav' -o -iname '*.mp3' \) -execdir ffmpeg -i "$(basename "{}")" -qscale:a 6 "${$(basename "{}")%.*}.ogg" \; Try: find samples \( -iname '*.wav' -o -iname '*.mp3' \) -exec sh -c 'ffmpeg -i "$1" -...



Top 50 recent answers are included