0

I've been trying:

find dev-other -name '*.flac' -type f -exec echo $(echo {} | sed 's,^[^/]*/,,') \;

I expect to see a list of paths to .flac files within dev-other, but without a prepended dev-other/, e.g.:

4515/11057/4515-11057-0095.flac
4515/11057/4515-11057-0083.flac
4515/11057/4515-11057-0040.flac
4515/11057/4515-11057-0105.flac
4515/11057/4515-11057-0017.flac
4515/11057/4515-11057-0001.flac

Instead I see

dev-other/4515/11057/4515-11057-0095.flac
dev-other/4515/11057/4515-11057-0083.flac
dev-other/4515/11057/4515-11057-0040.flac
dev-other/4515/11057/4515-11057-0105.flac
dev-other/4515/11057/4515-11057-0017.flac

Why isn't the sed replace working here even though it works on its own

$ echo $(echo dev-other/4515/11057/4515-11057-0047.flac | sed 's,^[^/]*/,,')
4515/11057/4515-11057-0047.flac

I first tried with expansions:

find dev-other -name '*.flac' -type f -exec a={} echo ${a#*/} \;

But got the errors:

find: a=dev-other/700/122866/700-122866-0001.flac: No such file or directory
find: a=dev-other/700/122866/700-122866-0030.flac: No such file or directory
find: a=dev-other/700/122866/700-122866-0026.flac: No such file or directory
find: a=dev-other/700/122866/700-122866-0006.flac: No such file or directory
find: a=dev-other/700/122866/700-122866-0010.flac: No such file or directory
Inian
  • 80,270
  • 14
  • 142
  • 161
theonlygusti
  • 11,032
  • 11
  • 64
  • 119
  • Interesting question, and the answer of why `sed` not work is probably here, https://stackoverflow.com/questions/4793892/recursively-rename-files-using-find-and-sed – CWLiu Oct 19 '17 at 08:15

1 Answers1

0

You can just use parameter expansion for your use-case when using find with the -exec option,

find dev-other -name '*.flac' -type f -exec bash -c 'x=$1; y="${x#*/}"; echo "$y"' bash {} \;

I used a separate shell (use bash or sh) using bash -c because to involve separate string operations involving parameter expansion. Think of each output of find result to be passed as argument to this sub-shell where this manipulation takes place.

When bash -c executes a command, the next argument after the command is used as $0 (the script's "name" in the process listing), and subsequent arguments become the positional parameters ($1, $2, etc.). This means that the filename passed by find (in place of the {}) becomes the first parameter of the script -- and is referenced by $1 inside the mini-script

If you don't want to use an extra bash, use _ in-place

find dev-other -name '*.flac' -type f -exec bash -c 'x=$1; y="${x#*/}"; echo "$y"' _ {} \;

where _ i is a bash predefined variable (not defined in dash for instance): "At shell startup, set to the absolute path-name used to invoke the shell or shell script being executed as passed in the environment or argument list" ( See man bash - Special Parameters section)

Worth looking at Using Find - Complex Actions

Inian
  • 80,270
  • 14
  • 142
  • 161
  • 1
    Why not just `... -exec sh -c 'echo "${1#*/}"' sh {} \;` ? You don't need so many auxiliary variables... – gniourf_gniourf Oct 19 '17 at 08:23
  • @gniourf_gniourf : Yes but I’d argue using an extra variable, I could demonstrate how the output of find is being parsed inside the sub shell as $1 . It could be still be avoided though ;) – Inian Oct 19 '17 at 08:31