How do I extract a file name into 2 parts, making one into directory and the other one inside of it?

前端 未结 4 1724
轮回少年
轮回少年 2020-12-21 18:54

I\'m trying to sort all mp3 files by artist and name. At the moment, they\'re in 1 giant file name. E.g Artist - Song name.mp3 I want to convert this to Artist/Song name.mp

相关标签:
4条回答
  • 2020-12-21 19:21

    Just in case you don't have the rename utility. A fix on your original script.

    for f in *.mp3; do
      # extract artist and song name and remove spaces
      artist=${f%% -*}
      song=${f##*- }
      #make directory with the extracted artist name and move + rename the file into the directory
      echo mkdir -p -- "$artist" && echo mv -- "$f" "$artist/$song"
    done
    
    • Remove the echo If you're satisfied with the output.
    0 讨论(0)
  • 2020-12-21 19:34

    By far the simplest way of doing this is to use rename a.k.a. Perl rename.

    Basically, you want to replace the sequence SPACE-DASH-SPACE with a forward slash directory separator, so the command is:

    rename --dry-run -p 's| - |/|' *mp3
    

    Sample Output

    'Artist - Song name.mp3' would be renamed to 'Artist/Song name.mp3'
    'Artist B - Song name 2.mp3' would be renamed to 'Artist B/Song name 2.mp3'
    

    If that looks correct, just remove --dry-run and run it again for real. The benefits of using rename are:

    • it can do a dry-run to test before you run for real
    • it will create all necessary directories with the -p option
    • it will not clobber (overwrite) files without warning
    • you have the full power of Perl available to you and can make your renaming as sophisticated as you wish.

    Note that you can install on macOS with homebrew:

    brew install rename
    
    0 讨论(0)
  • 2020-12-21 19:36

    Assuming there are many files, it's probably much faster to do this using pipes instead of a for loop. This has the additional advantage of avoiding complicated bash-specific syntax and using core unix/linux command line programs instead.

    find *-*.mp3 |
      sed 's,\([^-]\+\)\s*-\s*\(.*\),mkdir -p "\1"; mv "&" "\1"/"\2",' |
      bash
    

    Explanation:

    This find to find all the files matching -.mp3 in the current directory.

    This sed command changes each line to a command string, e.g.:

    aaa - bbb.mp3
    ->
    mkdir -p "aaa"; mv "aaa - bbb.mp3" "aaa"/"bbb.mp3"
    

    The bash command runs each of those command strings.

    0 讨论(0)
  • 2020-12-21 19:37

    you can try this.

    #!/usr/local/bin/bash
    for f in *.mp3
    do
    artist=`echo $f | awk '{print $1}' FS=-`
    song=`echo $f | awk '{print $2}' FS=-`
    mkdir -p $artist
    mv $artist-$song $song
    mv $song ./$artist
    done
    

    here I am using two variable artist and song. as your test file name is "hi\ -\ hey" so I change the awk delimiter to "-" to store variable according to it.

    we don't need to use awk..by using bash parameter expansion.... it is working.

    #!/usr/local/bin/bash
    for f in *.mp3
    do
    artist=`echo ${f%-*}`
    song=`echo ${f#*-}`
    mkdir -p $artist
    mv $artist-$song $song
    mv $song ./$artist
    done
    
    0 讨论(0)
提交回复
热议问题