Hot answers tagged

26

Bad Things ® ™. It's (almost) the equivalent of sudo rm -rf / - it will, as root, find all files or directories starting from / and recursively descending from there, and then execute the rm command against each file/directory it finds. It won't actually delete directory entries as there's no -f or -r options passed to rm, but it will remove all ...


26

-delete implies -depth that doesn't work with -prune (-depth starts with the leaves). There's a warning about that in the manual of the GNU version (-delete is a GNU extension now also supported by FreeBSD find). info find --index-search=-delete The use of the '-delete' action on the command line automatically turns on the '-depth' option (*note ...


17

find . -type f ! -newermt "31 Dec 2014" find(1): -newerXY reference Compares the timestamp of the current file with reference. The reference argument is normally the name of a file (and one of its timestamps is used for the comparison) but it may also be a string describing an absolute time. X and Y are ...


14

find traverses the specified directory tree(s), and evaluates the given expression for each file that it finds. The traversal starts at the given path. Here's a summary of how find . -name foo operates: First path on the command line: . Does the base name (.) match the pattern foo? No, so do nothing. It so happens that /tmp/foo is another name for the ...


14

Try: find . -name 'file.txt' -exec sed command {} + This finds all files named file.txt that in subdirectories of . and runs sed command against those files. If you want sed to modify those files in place, then add the -i option. Althought -exec ... + is now required by POSIX (hat tip: jordanm), some people may be using old versions of BSD find that do ...


13

GNU find has an optimization which can be applied to find . but not to find . -type f: if it knows that none of the remaining entries in a directory are directories, then it doesn't bother to determine the file type (with the stat system call) unless one of the search criteria requires it. Calling stat can take measurable time since the information is ...


13

Try: grep -rl --null --include '*.txt' LINUX/UNIX . | xargs -0r cp -t /path/to/dest Because this command uses NUL-separation, it is safe for all file names including those with difficult names that include blanks, tabs, or even newlines. The above requires GNU cp. For BSD/OSX, try: grep -rl --null --include '*.txt' LINUX/UNIX . | xargs -0 sh -c 'cp "$@"...


12

If you have GNU find, you can use -printf: find content/media/ -type f -printf '%p : %u : %g : %k'


12

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 ...


12

More portably (POSIX features only): find . -type f -name '*.txt' -exec grep -q LINUX/UNIX \; -exec cp {} /path/to/dest \;


11

Use this with bash: find $1 -name "* *.xml" -type f -print0 | \ while read -d $'\0' f; do mv -v "$f" "${f// /_}"; done find will search for files with a space in the name. The filenames will be printed with a nullbyte (-print0) as delimiter to also cope with special filenames. Then the read builtin reads the filenames delimited by the nullbyte and ...


11

If you run this command your touch file will be run, potentially multiple times, from the directory in which the command has been started: find -name '*.pdf' -exec touch file \; On the other hand, if you run this variant, each instance of the command will be run in the target file's directory: find -name '*.pdf' -execdir touch file \; In both cases you ...


11

This is a performance issue of find. In findutils version 4.3.4, a workaround had to restrict the number of arguments that -execdir ... {} + will use to 1. In version 4.5.9 the limit was removed. See an example: $ mkdir -p dir{1..3} $ touch dir{1..3}/file1 dir2/file{1..3} $ find . ./dir1 ./dir1/file1 ./dir2 ./dir2/file1 ./dir2/file2 ./dir2/file3 ./dir3 ./...


11

Found the details here: The -exec action causes another program to be run. It passes to the program the name of the file which is being considered at the time. The invoked program will typically then perform some action on that file. Once again, there is a race condition which can be exploited here. We shall take as a specific example the command ...


11

Use stat on the -exec action of find: find .content/media/ -type f -exec stat -c '%n : %U : %G : %s' {} + Change the format sequences of stat to meet your need.


11

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' *


10

You are on the right track (for a simpler solution, running only 2 or 3 commands, see below). You should use * instead of ./ to get rid of the current directory¹ and this simplifies cutting of the milliseconds somewhat, then just pipe the result into GNU parallel or xargs²: find * -type d | cut -c 1-10 | parallel date --date=@{} +%c to get Sat 12 Sep ...


10

I'd avoid running several commands per file in a loop. Since you're already using GNUisms: find . ! -name . -prune -type d | awk '{t = substr($0, 3, 10); print t, strftime("%a %b %d %T %Z %Y", t)}' Which just runs two commands. strftime() is GNU-specific, like date -d.


10

It's not an endless looping, it's just GNU find reporting that echo died of a SIGPIPE (because the other end of the pipe on stdout has been closed when head died). -execdir is not specified by POSIX. And even for -exec, there's nothing in the POSIX spec that says that if the command is killed by a SIGPIPE, find should exit. So, would POSIX specify -execdir,...


10

These examples work in any POSIX shell and require no external programs. This stores the Part*.mp3 files at the same level as the Project directory: (cd Project && for i in Part*/audio.mp3; do echo mv "$i" ../"${i%/*}".mp3; done) This keeps the Part*.mp3 files in the Project directory: for i in Project/Part*/audio.mp3; do echo mv "$i" ./"${i%/*}"...


10

Use -prune to ignore those directories: find /path/to/directory -name '*[0-9]*' -prune -o -type d -print though if you're on a gnu setup you may want to use the C locale when running the above, see Stéphane's comment below.


10

You can use fdupes. From man fdupes: Searches the given path for duplicate files. Such files are found by comparing file sizes and MD5 signatures, followed by a byte-by-byte comparison. You can call it like fdupes -r /path/to/dup/directory and it will print out a list of dupes. Update You can give it try to fslint also. After setting up fslint, go to ...


9

You can combine multiple predicates by chaining them. There's no -oldermt, but you can write that as -not -newermt. You want: -newermt '-15 seconds' to say the file is less than 15 seconds old, and -not -newermt '-2 seconds' to say the file is more than 2 seconds old Try: find /my/directory -newermt '-15 seconds' -not -newermt '-2 seconds' Or, to ...


9

Yes, there are several ways to accomplish this with the find command. I'll list some in the order that I think is important for understanding in your situation. Your script appears to accept multiple filename arguments, so the most efficient and nearly universal way to accomplish this using the find command is: find ~/foo -type f -name \*.txt -exec perl ~...


9

That's because grep can't read file names to search through from standard input. What you're doing is printing file names that contain XYZ. Use find's -exec option instead: find . -name "*ABC*" -exec grep -H 'XYZ' {} + From man find: -exec command ; Execute command; true if 0 status is returned. All following arguments to find ...


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 &&...


8

Using rename find . -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \; or with $1 find "$1" -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \; Using mv find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \; or with $1 find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;


8

Don't run it. This will find everything (all files, directories, links, sockets etc) under / i.e. everything in the system and then it will try to remove those one at a time with rm. Note that as there is no -r option with rm, only the directory entries will not be removed, everything else will be gone.


8

You already have: find ./ -type d | cut -c 3-12 which presumably gets you the timestamps in epoch format. Now add a while loop: find ./ -type d | cut -c 3-12 | while read datestamp do printf %s "$datestamp" date -d "@$datestamp" done Note though that in some shells, that syntax gets the while loop in a subshell, which means that if you try to ...


8

I would execute a find inside another find. For example, I would execute this command line in order to list the files that would be removed: $ find /path/to/source -type d -name 'rules' -exec find '{}' -mindepth 1 -maxdepth 1 -type f -iname '*.pdf' -print ';' Then, after checking the list, I would execute: $ find /path/to/source -type d -name 'rules' -...



Only top voted, non community-wiki answers of a minimum length are eligible