I have a directory full of albums I've ripped to FLAC format. Folders are named "Artist - Album [flac]" I need to create matching directories named "Artist - Album [mp3]" but only for certain folders...

So "ls | grep Pantera" gives me the list of directories I want to work with...

How can do I do this via command line?


You can use xargs to use the output of one command as arguments to run another; but but using the output of ls for this is crazy problematic because of spaces and quoting issues. In order to accomplish what you are suggesting if there are any spaces in the names produced you would have to do something like this:

ls | grep Pantera | sed -e 's/\[flac\]/[mp3]/' | xargs -n1 -i{} mkdir "{}"

However the a much better tool for this would be to use the find command and -exec option. Unless someone knows how to make use of bash's string functions on a literal string instead of a variable or set and use a variable in one command, you will need ssapkota's syntax to launch a subshell.

When using find, also consider options such as -type d to only return directory matches (or -type f for files). You could remove the -maxdepth 1 if you wanted to do a recursive find. It's also possible the pattern matching could be refined for your scenario.

  • I also agree in utilizing find, but the command line provided is incomplete. It does not create a [mp3] from a [flac] dir. – forcefsck Jun 13 '11 at 15:39
  • You're quite right. I'll fix this to answer the whole problem not just the output as arguments problem. – Caleb Jun 13 '11 at 15:46
  • The second answer you gave isn't working. It throws a find: missing argument to -exec – LVLAaron Jun 13 '11 at 17:26
  • Hmmm ... might need to escape those &'s ... or drop them. Hang on I'll figure it out. – Caleb Jun 13 '11 at 21:27
  • @Caleb: You need to invoke a shell as the -exec command. ssapkota's answer shows how. – Gilles Jun 13 '11 at 21:41

Find is the best tool for it. But find just allows a single command and doesn't support chaining.

Here's the solution that works by forking a subshell for each matched directory name.

find -maxdepth 1 -iname "*Pantera*" -exec  \
    bash -c ' name="{}" && mkdir "${name/flac/mp3}" ' \;

Are all the files in the same directory? Then you can use a simple loop plus shell string manipulation constructs.

for flac_dir in *Pantera*'[flac]'/; do
  mkdir "$mp3_dir"

If you want to act recursively in subdirectories as well, under zsh, or under bash ≥4, you can use for flac_dir in **/*Pantera*'[flac]'/. With bash, you need to run shopt -s globstar first.

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.