Tag Info

Hot answers tagged

11

You can prevent the file from reaching xargs using: find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\n' | xargs -r shasum -- > sums.sha1 To prevent problems with filename that have blanks or newlines or quotes or backslashes, I would however use: find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\0' | xargs -r0 shasum -- > ...


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.


8

The basic format of find is find WHERE WHAT So, in find *, the * is taken as the WHERE. Now, * is a wildcard. It matches everything in the current directory (except, by default, files/directories starting with a .). The Windows equivalent is *.*. This means that * is expanded to all files and directories in your current directory before it is passed to ...


7

If you understand the && and || operators in the shell (and also in C, C++, and derivative languages), then you understand -a and -o in find. To refresh your memory: In the shell, command1 && command2 runs command1, and, if it (command1) succeeds, it (the shell) runs command2. command1 || command2 runs command1, and, if it (command1) fails, ...


7

Try this: find /tmp/ -type f -name "*.h" -o -name "*.cpp" \ -exec sed -i '1s/^/#include <stdint.h>\n/' {} + Also, as correctly pointed out to me, the ! -name "*.bak" is superfluous. The -name *foo pattern only matches files ending with foo. Therefore, the *.cpp and *.h already exclude *.bak.


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


6

It looks like you want to avoid looking for files in *cache* directories more than finding files with *pillar* and not *cache* in their name. Then, just tell find not to bother descending into *cache* directories: find . -iname '*cache*' -prune -o -iname '*pillar*' -print Or with zsh -o extendedglob: ls -ld -- (#i)(^*cache*/)#*pillar* (not strictly ...


6

The find options you've specified apply on the filename, not on the name of sub-directories. Here, your filename doesn't contain cache but contains pillar, so it matches. In your case, you may want to use the -path option. Something like: find . -iname '*pillar*' -and -not -ipath '*cache*'


6

These are not part of bash; find is a standalone program and does not require bash or even a POSIX shell to run. For example, it works fine with fish, which is not POSIX compliant and does not follow all the same syntax rules as bash. You could, in fact, use it with no shell at all (e.g., in a programmatic context). This is why (if you are using a POSIX ...


5

The order of find arguments matters. The command needs to be constructed as find -type d -print0 and then it will work as expected. I just thought I'd post this in case it's helpful to anyone.


5

Since you're using -maxdepth 1, I assume you don't want recursion. If so, just do it in the shell instead: for f in ~/test/*; do shasum -- "$f" done > sums.sha1 To skip directories, you can do: for f in ~/test/*; do [ ! -d "$f" ] && shasum -- "$f" done > sums.sha1 If you do need recursion and are using bash, do: shopt -s globstar ...


5

You can use -o for logical OR. Beware however that all find predicates have logical values, so you'll usually need to group ORed things together with parens. And since parens also have a meaning to the shell, you'll also need to escape them: find /some/dir -maxdepth 1 \( -name '*.c' -o -name '*.h' \) -print


4

Don't use find for this - whichever way you go with find you'll need something like a single mv per file. That's a lot of processes, and to no benefit. This is not to mention that it is simply more difficult to do that way. That's my opinion, anyway. I would use a stream or a batch tool, and tend to prefer pax: cd -P . && mkdir ../newmp4 ...


4

Use find -exec for recursive touch, with command line args for dirs to process. #!/bin/sh for i in "$@"; do find "$i" -type f -exec touch -r {} -d '+3 hour' {} \; done You can run it like this: ./script.sh /path/to/dir1 /path/to/dir2


4

To improve the huge speed impact on find you could simulate something like locate alias locate="if [ ! -e /tmp/locate.db -a ! -e /tmp/locate.lockdb ] then touch /tmp/locate.lockdb trap \"rm /tmp/locate.lockdb; rm /tmp/locate.db; exit\" SIGHUP SIGINT SIGTERM find /|tee /tmp/locate.db chmod 666 /tmp/locate.db rm /tmp/locate.lockdb elif [ -e /tmp/locate.lockdb ...


4

Although both curly braces {,} and semicolons ; do have special meanings in bash, in this case it is the find command itself that is interpreting them, not the shell. The -ok command of find uses the same syntax as its -exec command, so you will find a complete description in that section of its manual page (man find): -exec command ; Execute ...


4

with zsh: shasum -- *(D.) > sums.sha1 The glob will be expanded before the redirection is made, so the sums.sha1 will not be included if it was not there in the first place. D is to include dot-files (hidden files) as find would. . is to select only regular files (like your -type f). To exclude the sums.sha1 anyway in case it was there in the first ...


4

The GNU implementation of grep (also found in most modern BSDs though the latest versions are a complete (mostly compatible) rewrite) supports a -o option to output all the matched portions. LC_ALL=C grep -ao CDA | wc -l would then count all the occurrences. LC_ALL=C grep -abo CDA to locate them with their byte offset. LC_ALL=C makes sure grep doesn't ...


3

You could do: find . -name '*.png' | awk -F/ '{print tolower($NF)}' | sort -u > ~/tmp/png-files && grep -IhFriof ~/tmp/png-files --exclude-dir=".svn" . | awk '{print tolower($0)}' | sort -u | comm -23 ~/tmp/png-files - That would give you the lower-case names of the png files that are never referenced. The first pipeline builds a sorted ...


3

The example in your question looks like the ls -l output, not the lsattr output. In the ls -l output, the first field is the mode, that is the type (regular, directory, symlink...) and permissions. The S bit at that position means setuid but without execute permission for the user. Here given that none of user/group/other have execute permissions, that ...


3

find -perm Is what you want - it'll allow you to specify an octal mode for 'find' to ... well, find. You can find which perm to look for with 'stat' which will give you what it currently is. So e.g. find . -perm 4750 I don't recognise your bit flags well enough to tell you the octal mode of them, so you'll have to look for yourself. Edit: As ...


3

function locate_f() { find / -path "*$1*" //Edit:path (as Gilles stated) } alias locate=locate_f


3

I'd use1 find with two -exec actions e.g.: find . -type f -exec grep -qF SOME_STRING {} \; -exec sed 'COMMAND' {} \; The second command will run only if the first one evaluates to true i.e. exit code 0 so sed will process the file in question only if the file contains SOME_STRING. It's easy to see how it works: find . -type f -exec grep -qF SOME_STRING {} ...


3

Get the file size: size="$(stat --printf="%s" "$path")" Get the path without the last extension: path_without_extension="${path%.*}" Compare the two: [ "${path_without_extension}.${size}" = "$path" ]


3

find <path>/. -type f -size 1033c ! -perm -0001 -ls


2

The find manual page explains: -perm +mode Deprecated, old way of searching for files with any of the per‐ mission bits in mode set. You should use -perm /mode instead. Trying to use the `+' syntax with symbolic modes will yield sur‐ prising results. […] So yes, they're the same thing, but you should use ...


2

The trick to understand a find command is to recursively evaluate and group into the resulting logic value's appropriate expression (-true or -false) the first two expressions / actions, considering that the evaluation of each pair of expressions / actions is short-circuited (hence expressions / actions as the second operand of an AND comparison will not be ...


2

You are almost there. In your last command, you can use -I to do the ls correctly -I replace-str Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not terminate input items; instead the separator is the newline character. Implies -x and -L 1. So, with find . ...


2

If you found that answer, there would be nothing else special. $ cd /path/to/srcdir $ grep -lr PATTERN . | tar -T - -cf - | tar -C /path/to/dstdir -xf -


2

find /some/path -name '*boost*' -name '*Qt*' Or to match on the full path: find /some/path -path '*boost*' -path '*Qt*' If you don't quote those patterns, they'll be expanded by your shell first. For case insensitive match, some find implementations have -iname/-ipath. Otherwise, you can always do: find /some/path -name '*[bB][oO][oO][sS][tT]*' -name ...



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