Skip to main content
deleted 66 characters in body
Source Link
Stéphane Chazelas
  • 586.2k
  • 96
  • 1.1k
  • 1.7k

With the next version of GNU find, you'll also be able to do:

Also note that -name matches on the name of the file, not its full path (for which you need -path). So we need [[:upper:]]* not /[[:upper:]]* (nor [A-Z]* where what it matches on is often rather random depending on the locale) to match on filenames that start with an uppercase letter.

find / -maxdepth 1 -name '[[:upper:]]*' -type d -print0 | find -file0files0-from - -name X -type d 

With the next version of GNU find, you'll also be able to do:

Also note that -name matches on the name of the file, not its full path (for which you need -path). So we need [[:upper:]]* not /[[:upper:]]* (nor [A-Z]* where what it matches on is often rather random depending on the locale) to match on filenames that start with an uppercase letter.

find / -maxdepth 1 -name '[[:upper:]]*' -type d -print0 | find -file0-from - -name X -type d 

Also note that -name matches on the name of the file, not its full path (for which you need -path). So we need [[:upper:]]* not /[[:upper:]]* (nor [A-Z]* where what it matches on is often rather random depending on the locale) to match on filenames that start with an uppercase letter.

find / -maxdepth 1 -name '[[:upper:]]*' -type d -print0 | find -files0-from - -name X -type d 
added 1284 characters in body
Source Link
Stéphane Chazelas
  • 586.2k
  • 96
  • 1.1k
  • 1.7k

Note that with some find implementations on some systems (including GNU find on GNU systems), * may fail to match parts of file names that are not valid text in the current locale.

For example, the command above would find /stéphane/X even though s is not an uppercase letter if that é was encoded in iso8859-1 and the current locale was using UTF-8 as its charmap (where the 0xe9 byte there could not be decoded into a character so * couldn't match across it), and the first command would fail to find /Stéphane/X for the same reason.

zsh globs don't have this kind of problem as the treat each byte that can't be decoded into a character as if it was an undefined character, so you could do:

print -rC1 /[[:upper:]]*/**/X(ND/) 

Or as a slight optimisation if you don't need the list to be ordered:

print -rC1 /[[:upper:]]*/**/X(ND/oN) 

Note that it would include /SymLink/.../X dirs. To avoid that:

(){print -rC1 $^@/**/X(ND/oN)} /[[:upper:]]*(N/oN) 

or:

print -rC1 /[[:upper:]]*(N/oNe['reply=($REPLY/**/X(ND/oN)']) 

Which are like the two stage find approaches: find the directories whose name starts with an uppercase letter in one glob and then all the X dirs in them as separate globs.

Note that with some find implementations on some systems (including GNU find on GNU systems), * may fail to match parts of file names that are not valid text in the current locale.

For example, the command above would find /stéphane/X even though s is not an uppercase letter if that é was encoded in iso8859-1 and the current locale was using UTF-8 as its charmap (where the 0xe9 byte there could not be decoded into a character so * couldn't match across it), and the first command would fail to find /Stéphane/X for the same reason.

zsh globs don't have this kind of problem as the treat each byte that can't be decoded into a character as if it was an undefined character, so you could do:

print -rC1 /[[:upper:]]*/**/X(ND/) 

Or as a slight optimisation if you don't need the list to be ordered:

print -rC1 /[[:upper:]]*/**/X(ND/oN) 

Note that it would include /SymLink/.../X dirs. To avoid that:

(){print -rC1 $^@/**/X(ND/oN)} /[[:upper:]]*(N/oN) 

or:

print -rC1 /[[:upper:]]*(N/oNe['reply=($REPLY/**/X(ND/oN)']) 

Which are like the two stage find approaches: find the directories whose name starts with an uppercase letter in one glob and then all the X dirs in them as separate globs.

edited body
Source Link
Stéphane Chazelas
  • 586.2k
  • 96
  • 1.1k
  • 1.7k
find / -maxdepth 1 -type d -name '[[:upper:]]*' -type d -exec sh -c ' exec find "$@" -name X -type d' sh {} + 
find / -maxdepth 1 -type d -name '[[:upper:]]*' -type d -print0 | find -file0-from - -name X -type d 

Where we tell find to prune the branches of the tree that start with directories in / whose name starts by any character other than an uppercase letter before looking for directory named X.

(that one would also report /X itself if it existed as a directory)

find / -maxdepth 1 -type d -name '[[:upper:]]*' -exec sh -c ' exec find "$@" -name X -type d' sh {} + 
find / -maxdepth 1 -type d -name '[[:upper:]]*' -print0 | find -file0-from - -name X -type d 

Where we tell find to prune the branches of the tree that start with directories in / whose name starts by any character other than an uppercase letter before looking for directory named X.

(that one would also report /X itself if it existed as a directory)

find / -maxdepth 1 -name '[[:upper:]]*' -type d -exec sh -c ' exec find "$@" -name X -type d' sh {} + 
find / -maxdepth 1 -name '[[:upper:]]*' -type d -print0 | find -file0-from - -name X -type d 

Where we tell find to prune the branches of the tree that start with directories in / whose name starts by any character other than an uppercase letter before looking for directory named X.

Source Link
Stéphane Chazelas
  • 586.2k
  • 96
  • 1.1k
  • 1.7k
Loading