Hot answers tagged

6

Not using find, but globbing in the zsh shell: $ printf '%s\n' **/foo/*(^/) a/b/c/foo/z a/b/foo/y a/foo/x foo/w This uses the ** glob, which matches "recursively" down into directories, to match any directory named foo in the current directory or below, and then *(^/) to match any file in those foo directories. The (^/) at the end of that is a glob ...


4

Quotes are not processed in the output of expansions. If you do $(echo '"foo bar"'), or $(echo "\"foo bar\""), what ends up as the argument to the main command is "foo and bar". With literal quotes, and as two distinct arguments due to word splitting. By default, word splitting happens on any whitespace, spaces or newlines, so from the output of find, you ...


4

The -prune predicate prunes directories - in this case, -name will match the starting directory . and hence prune the whole tree. What you want to do is simply negate the -name match: find . -maxdepth 1 ! -name '.*' or find . -maxdepth 1 -not -name '.*'


4

What's the point of using a regex here? Why not just use find /var/spool/mail/ -type f? and use -maxdepth 1 if you want to prevent recursion into any sub-directories. Also, why truncate the user mailboxes when you can just delete them? e.g. find /var/spool/mail/ -type f -delete or find /var/spool/mail/ -type f -exec rm {} + When new mail arrives for ...


3

I'm on RHEL 7. This works for me: find . -path "*/foo/*" ! -path '*/foo/*/*' -type f Note the DOT before the -path. (Or substitute your path there, such as /home/$USER) The DOT says "Start looking in the current directory" the -path says "Look for anything, followed by a sub-directory named foo, followed by anything" except for directories nested ...


3

** has no special meaning in find patterns. -path '*/foo/*' would find all files under a directory called foo, including files in subdirectories. -path '*/foo/*' ! -path '*/foo/*/*' would exclude files like a/foo/b/foo/c. I don't think you can do this with just one invocation of POSIX find. With find implementations that support -regex (GNU, BusyBox, ...


3

(Unless you are using zsh as your interactive shell...) The issue is that the double quotes will be taken as part of the pattern. The command that you are actually running would be the equivalent of find . -name '"Bik*"' You get this because the shell would perform word-splitting on the unquoted $a, splitting the string tho the two words -name and "Bik*". ...


3

find / -name 'dork*' ! -name '*.zip' You need to use two -name tests. One for matching dork* and one for matching *.zip. The second of these should be inverted (the !) so that the found names do not match it. There is always an implicit AND between the tests. Making the implicit ANDs visible: find / -name 'dork*' -a ! -name '*.zip' Also using non-...


3

Use readarray to read the names into an array names. Then loop each of the elements in the array to do the find command. readarray names < names.txt for n in ${names[@]};do find . -type f -name "${n}.iso" done


3

You seem to want to truncate the mailboxes for all users. You can't do this by calling : from find as : is not an external utility (it's a shell built-in utility). Using true instead of : would have worked since that is commonly available as an external command, but... You also can't use a redirection in the command executed via -exec since that ...


3

It would be easier with zsh: names=(${(f)"$(<name-list.txt)"}) ls -ld -- **/(${(j:|:)~${(b)names}}).iso(D) Where: $(<file) ksh-style operator that expands to the content of file f parameter expansion flag the splits on linefeeds, so we store in $names the lines of name-list.txt ${(b)var} escapes the glob operators in the content of $var. j:|:: ...


3

You could do it with find, but you could also use a shell loop: for dir in /home2/blogname/* do [ -d "$dir"/public_html/wp-content/plugins/better-wp-security ] || printf '%s is missing a public_html/wp-content/plugins/better-wp-security directory\n' "$dir" done With GNU find: find /home2/blogname -mindepth 1 -maxdepth 1 -exec sh -c \ 'test ! -d "$1"/...


3

This command will do it nicely: find . -type f ! -exec grep -q '[^[:space:]]' {} \; -print


2

The $() expands properly, but the shell does more to the result than what you are aware of. Additionally, adding literal quotes to pathnames is almost never the correct thing to do (unless you are using eval somewhere). To play all the MP3 files in or under ~/Documents/music using vlc: find ~/Documents/music -type f -name '*.mp3' -exec vlc {} + This ...


2

Best to learn about a command is to read its manual info ls/info find or man ls/man find. Or the POSIX specification of each to learn about the subset that should be common to all different implementations. The syntax for find is find [options] <file1> [<file2>...] [predicates] (some find implementations allow skipping <file1>) And ls: ...


2

You could cd into folderA and run the command from there: cd folderA find . -type d -o -type f -exec bash -c ' for path; do mkdir -p "/path/to/folderB/${path/file/folder}"; done ' bash {} + The parameter expansion ${path/file/folder} renames the each fileXY to folderXY. If every folder contains files, you can remove the -type d -o.


2

You can do "or" tests in find: find . -name a -o -name b .... So, modifying your file to add the switches, and using xargs to build the find command: awk 'NR > 1 {print "-o"}; {print "-name", $0".iso"}' input-file | xargs find . For a sufficiently small list, this should run only one find. If you have blanks, quotes or other special characters in the ...


2

You want to run your function then act on its output, that's command substitution, so it's either this: for f in `find_files` or this: for f in $(find_files) These 2 syntax are equivalent, but the first one is old-style, the latter one is new . Check bash documentation on command substitution. Further more it's probably not a good idea to loop ...


2

Here, it would be easier with dedicated file renaming tools like prename, mmv or zsh's zmv. But if you have to use POSIX sh and utilities, I'd do things like: find . ! -name . -prune \( -name '*.xxx' -o -name '*.yyy' \) -type f -exec sh -c ' ret=0 for file do name=${file##*/} dstdir=Out/$(printf "%s\n" "${name%%-*}" | tr -s "[:space:]" "[_*]") ...


2

If you can guarantee that file and directory names won't contain newline characters, one method is to find all files, then use grep to match only the desired results: find . -type f | grep '/foo/[^/]*$'


1

steeldriver pinpoints some of the issues with your command, but I just wanted to add a shorter solution using the zsh shell (as the question was not specific to any one shell): cp -- *.jpg(.[1,100]) ~rachel/backup This would copy the 100 first (by lexicographic ordering) regular files in the current directory that matches the globbing pattern *.jpg. For ...


1

A couple of things: You're missing a -I in your xargs command to tell it what the {} is to be used for The -0 tells xargs to expect null-delimited input, but you're passing it newline-delimited input So find . -maxdepth 1 -name '*.jpg' -print0 | head -zn 100 | xargs -0 -I{} cp {} /home/rachael/backup If you have the GNU version of cp, you might want to ...


1

As @Jonas noted, you need a ? to match one character and a * to match multiple characters. A space character needs to be escaped with a \. With the first pattern **-**** ? changed to ??-????\ * and the escaped space characters, the command should be: cp -r /volume1/User/save/01/??-????\ */GROUPES\ ??-????/ /volume1/User/save/01/


1

You can set the number of workers if you use xargs find ./* -type f -print0|xargs -0 -P 16 -I % opusenc --bitrate 256 % %.opus xargs -P 16 (since I struggled to find more details online or understand the man page section) It does your command on 16, or the number you pass to -P, of the inputs at a time. For my command I was trying to convert an ...


1

You're misunderstanding the syntax for the find expression. I think you're expecting the -name test to treat "dork*" -and !"zip" as the pattern it looks for, but -name expects a single pattern string, not some sort of expression. The way find is parsing it is: (the name matches dork*) and (!zip), with !zip being a separate subexpression from the -name ...


1

I had a similar requirement and ended up using the -I switch to have a placeholder and I was able to quote it. find . -size +1M | xargs -I {} rm "{}"


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