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


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


12

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


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.


10

See the man page for updatedb, "If the database already exists, its data is reused to avoid rereading directories that have not changed". Whereas the find command traverses all directories regardless of whether they have changed.


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


7

You can use : find . -type f -printf '%p::' | sed 's/::$/\n/' The -printf predicate of find will print the file names in a single line delimited by :: and then sed will substitute the last :: with a newline. Example : $ find . -type f -printf '%p\n' ./foo ./test ./bar $ find . -type f -printf '%p::' | sed 's/::$/\n/' ./foo::./test::./bar


7

find will set its return code to non-zero if it saw an error. So you can do: if ! find ... then echo had an error >&2 fi | while ... (I'm not sure what you want to do with the find output). To collect all the error messages from find on stderr (file descriptor 2) you can redirect 2 to a file. Eg: if ! find ... 2>/tmp/errors then ...


7

Would silencing the error stream be a solution? find / -type d -name 'force_fields' 2>/dev/null


7

You can use the -t option of GNU cp: -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY You should also use find's -print0 and xargs -0 otherwise, this will fail on file names with spaces or other weird characters: find . -amin -1440 -print0 | xargs -O cp -t /dest A better approach might be to use find itself and ...



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