Question

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
Was it helpful?

Solution

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

OTHER TIPS

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.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top