0

I have a bash script which parses a file line by line, extracts the date using a cut command and then makes a folder using that date. However, it seems like my variables are not being populated properly. Do I have a syntax issue? Any help or direction to external resources is very appreciated.

#!/bin/bash

ls | grep .mp3 | cut -d '.' -f 1 > filestobemoved

cat filestobemoved | while read line

do
    varYear= $line | cut -d '_' -f 3
    varMonth= $line | cut -d '_' -f 4
    varDay= $line | cut -d '_' -f 5

    echo $varMonth
    mkdir $varMonth'_'$varDay'_'$varYear

    cp ./$line'.mp3' ./$varMonth'_'$varDay'_'$varYear/$line'.mp3'  
done
4
  • Don't parse the output of ls please and thank you. Commented Apr 21, 2014 at 14:02
  • For a quick (but horrible) fix: varYear=$(echo $line | cut -d '_' -f 3). Commented Apr 21, 2014 at 14:05
  • What is the format of your file names? is it field1_field2_YYYY_MM_DD.mp3 or field1_field2_YYYY_MM_DD_someotherstuff.mp3 or could it be both? Commented Apr 21, 2014 at 14:24
  • Note that files such as pink.floyd.the.wall.mp3 will be chopped to pink by your first cut. If you have no names with dots before the .mp3 extension, this doesn't matter. Commented Apr 21, 2014 at 14:25

2 Answers 2

4

You have many errors and non-recommended practices in your code. Try the following:

for f in *.mp3; do
    f=${f%%.*}
    IFS=_ read _ _ varYear varMonth varDay <<< "$f"
    echo $varMonth
    mkdir -p "${varMonth}_${varDay}_${varYear}"
    cp "$f.mp3" "${varMonth}_${varDay}_${varYear}/$f.mp3"
done
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the input, your example is working great. Between that and the resources that I0b0 gave me I think I have a much better handle on where to go from here. Again, thanks for the help!
0

The actual error is that you need to use command substitution. For example, instead of

varYear= $line | cut -d '_' -f 3

you need to use

varYear=$(cut -d '_' -f 3 <<< "$line")

A secondary error there is that $foo | some_command on its own line does not mean that the contents of $foo gets piped to the next command as input, but is rather executed as a command, and the output of the command is passed to the next one.

Some best practices and tips to take into account:

  • Use a portable shebang line - #!/usr/bin/env bash (disclaimer: That's my answer).
  • Don't parse ls output.
  • Avoid useless uses of cat.
  • Use More Quotes™
  • Don't use files for temporary storage if you can use pipes. It is literally orders of magnitude faster, and generally makes for simpler code if you want to do it properly.
  • If you have to use files for temporary storage, put them in the directory created by mktemp -d. Preferably add a trap to remove the temporary directory cleanly.
  • There's no need for a var prefix in variables.
  • grep searches for basic regular expressions by default, so .mp3 matches any single character followed by the literal string mp3. If you want to search for a dot, you need to either use grep -F to search for literal strings or escape the regular expression as \.mp3.
  • You generally want to use read -r (defined by POSIX) to treat backslashes in the input literally.

1 Comment

Thanks for the resources, Between you and chenper I think I have a much better understanding of where to. It's greatly appreciated!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.