2

I'm trying to list all the files with names no longer than 250 characters (including the directory it is part of, from the relative path my command is inside).

I've seen a similar thread , but that will only list the files recursively.

Any idea on how to modify script to only show files with names no longer than 250 characters (including the relative path)?

  • possible duplicate of Find files by the length of filename – don_crissti Apr 29 '15 at 13:21
  • When I use this: find . -regextype posix-extended ! -regex '.{251,}' ! -type d It shows: find: unrecognized: -regextype I also tried : find . ! -path "$(printf %251s | tr ' ' '?')*" Unfortunately, for some reason, when i calculate the output, they are only 220 characters... – tuckker Apr 29 '15 at 16:14
4

With GNU find:

find . -regextype posix-extended ! -regex '.{253,}' ! -type d

(that prints a ./ prefix which is not included in the 250 count).

With zsh:

setopt extendedglob # if not already in your ~/.zshrc
printf '%s\n' **/*~?(#c251,)(D^/)

That's all paths recursively (**/*) including hidden ones ((D)), but not (^) those of type directory (/), except (~) those that match ?(#c251,), that is that contain 251 characters or more.

POSIXly:

find . ! -path "$(printf %253s | tr ' ' '?')*" ! -type d

(note that there's nothing on Unix that guarantees that file names are made of valid characters. Except for the zsh one, those solutions may also report files whose path contain sequences of bytes that don't form valid characters (adding -path '*' may help excluding those). If you want to match on the number of bytes as opposed to number of characters in your locale, you can fix the locale to C with export LC_ALL=C).

  • POSIX part is tricky, +1! – cuonglm Apr 29 '15 at 14:08
  • When I use this: find . -regextype posix-extended ! -regex '.{251,}' ! -type d It shows: find: unrecognized: -regextype I also tried : find . ! -path "$(printf %251s | tr ' ' '?')*" Unfortunately, for some reason, when i calculate the output, they are only 220 characters.... – tuckker Apr 29 '15 at 15:34
  • 1
    @tuckker. The first one requires GNU find. Yours is probably busybox find. 220 is not longer than 250, so by your requirements, those files should be listed. Update your question if that's not what you want. – Stéphane Chazelas Apr 29 '15 at 16:37
3

POSIXly:

$ find . -type f -exec sh -c '
    for f do
      [ "${#f}" -le 252 ] &&
      printf "%s\n" "$f"
    done
' sh {} +

POSIX defined ${#parameter} as the length in characters of value parameter, but the behaviour may varies in some shells. bash, zsh, yash count characters, dash count bytes. ksh93 has a random bug depends on its implementation.

  • Note that for paths that contain multi-byte characters or sequences of bytes that don't form valid characters, the behaviour varies across sh implementations (${#f} counts bytes in ksh and dash and characters in bash, zsh and yash; yash chokes on invalid characters). – Stéphane Chazelas Apr 29 '15 at 14:27
  • @StéphaneChazelas: Is it a weird behaviour since when POSIX specified that ${#parameter} is the length in characters of the value of parameter? – cuonglm Apr 29 '15 at 14:53
  • Yes, it's a bug in those shells. That was discussed on the austin group ml not so long ago. I was partly wrong for ksh above. ksh93 -c 'echo "${#1}"' sh $'\ue9\xe9' gives me 19, but that's a random bug in ksh93. With mksh, it gives me 3 but 2 with mksh -o utf8-mode. – Stéphane Chazelas Apr 29 '15 at 15:12
  • @StéphaneChazelas: I have ksh version sh (AT&T Research) 93u+ 2012-08-01 both in Debian and OSX. The one in OSX return 2, but Debian return 53 for your example. – cuonglm Apr 29 '15 at 15:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.