0

I want to create a list of mp3 files like a 1.mp3|a 2.mp3.

I have tried echo ${(j:|:)$(echo *.mp3)} and some variations of it, but they don’t work:

# too much splitting 
01|The|Magic|Finger|01.mp3|02|The|Magic|Finger|02.mp3|03|The|Magic|Finger|03.mp3|04|The|Magic|Finger|04.mp3|05|The|Magic|Finger|05.mp3|06|The|Magic|Finger|06.mp3

# too much quoting
01 The Magic Finger 01.mp3 02 The Magic Finger 02.mp3 03 The Magic Finger 03.mp3 04 The Magic Finger 04.mp3 05 The Magic Finger 05.mp3 06 The Magic Finger 06.mp3

I don’t want to create functions or variables for doing this. (It can be trivially done.)

4

It's a bit silly to get the list of mp3 files, pass them to echo so it can print them separated by spaces, then transfer that output over a pipe, read it, split on space/tab/newline/NUL, and then join with |.

Either do:

printf '%s|' *.mp3

Or

files=(*.mp3)
joined=${(j:|:)files}

If the purpose is for that to be used as a zsh pattern, you'll probably want to escape the wildcard characters in the names of those files. That is done with the b parameter expansion flag:

pattern="(${(j:|:)${(b@)files}})"
0

You can use set to glob those files into positional parameters and then "$*" to expand them with your desired field separator:

set -- *.mp3
(IFS=\|; echo "$*")

Note this is being done in a subshell so the changes to IFS don't affect your current shell.

  • I know, but I want to do it with substitutions and expansions. – HappyFace Aug 10 '19 at 20:31
  • Unnecessary and not as robust but if you really want to you could do set -- $(echo *.mp3). This will break on files with whitespace though. You could also arbitrarily do echo $(IFS=\|; echo "$*") but there is no reason to do that. – jesse_b Aug 10 '19 at 20:32
  • I mean I want it done all in one line. Like my own answer. 😅 – HappyFace Aug 10 '19 at 20:33
  • Virtually any group of shell commands can be done on one line with a liberal application of ; – jesse_b Aug 10 '19 at 20:33
0

I have found one way to do this, but it’s still rather convoluted for such a simple use case:

echo ${(j:|:)"${(@f)$(print -l *.mp3)}"}

  • This will break on files that contain newlines. – jesse_b Aug 10 '19 at 20:35
  • @Jesse_b If we should have a command to print them NUL separated, we can use (@0). I myself don’t have paths with new lines. – HappyFace Aug 10 '19 at 20:38
  • 2
    @Jesse_b, or backslash or that start with -. Here, you could do printf '%s\n'. You could do printf '%s\n' ${(j:|:)${(0)"$(printf '%s\0' *.txt)"}}, but again that feels quite silly. – Stéphane Chazelas Aug 10 '19 at 20:55

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.