[SOLVED]Simple question about bash

Programming languages, Coding, executables, and scripting.
Post Reply
Message
Author
pythagorasmk
Posts: 117
Joined: 2015-01-18 03:40

[SOLVED]Simple question about bash

#1 Post by pythagorasmk »

I am not so good in bash, so I have simple question.
I have some music in ALAC (m4a) files, distributed in sub directories (albums). I want to convert them in FLAC.
I am trying something like this:

Code: Select all

for i in */*.m4a; do ffmpeg -i "$i" ${i%m4a}wav; done
to convert them in WAV format, but expansion */*.m4a is not working, I get the error message from ffmpeg that */*.m4a does not exist.
How to solve the problem with expansion?
Last edited by pythagorasmk on 2020-11-12 20:07, edited 1 time in total.

User avatar
Bloom
Posts: 363
Joined: 2017-11-11 12:23

Re: Simple question about bash

#2 Post by Bloom »

You should use find to navigate through subdirectories.

However, there is a very good Bash script out there for converting various sound files to flac: https://www.legroom.net/software/convtoflac

I suggest you download it and study it. It's safe to use, by the way: I use it almost daily.

pythagorasmk
Posts: 117
Joined: 2015-01-18 03:40

Re: Simple question about bash

#3 Post by pythagorasmk »

Bloom wrote:
However, there is a very good Bash script out there for converting various sound files to flac: https://www.legroom.net/software/convtoflac

I suggest you download it and study it. It's safe to use, by the way: I use it almost daily.
Firefox tells me that legroom.net is not safe to browse. Do you have another link from where I can download the script.

User avatar
Bloom
Posts: 363
Joined: 2017-11-11 12:23

Re: Simple question about bash

#4 Post by Bloom »

You can copy it from here:

Code: Select all

#!/bin/bash

# -----------------------------------------------------------------------------
#
#	App Title:      convtoflac.sh
#	App Version:    2.1.5
#	Author:         Jared Breland <jbreland@legroom.net>
#	Homepage:       http://www.legroom.net/software
#
#	Script Function:
#		Convert losslessly compressed audio file to FLAC format, preserving tags
#		Currently supports FLAC, Monkey's Audio (APE), Shorten, WAV, and WavPack
#
#	Instructions:
#		Ensure that all programs are properly set in "Setup environment"
#
#	Caveats:
#		Transcoded files will retain original file name, but use .flac extension
#		The one exception is for FLAC input files - the original input file will
#			be renamed <name>_old.flac, and the transcoded file will be named
#			<name>.flac.
#
#	Requirements:
#		The following programs must be installed and available
#		sed (http://sed.sourceforge.net/)
#			used to handle case sensitivity and tag processing
#		trash-cli (http://code.google.com/p/trash-cli/))
#			used for moving files to trash rather than deleting
#		flac/metaflac (http://flac.sourceforge.net/)
#			used to create and tag new FLAC files
#		alac (http://craz.net/programs/itunes/alac.html)
#			used to decompress ALAC (Apple Lossles) files
#		mp4info, part of libmp4v2 (http://resare.com/libmp4v2/)
#			used to read tags from ALAC (Apple Lossles) files
#		mac (http://sourceforge.net/projects/mac-port/)
#			used to decompress APE (Monkey's Audio) files
#		apeinfo (http://www.legroom.net/software)
#			used to read tags from APE files
#		shorten (http://etree.org/shnutils/shorten/)
#			used to decompress Shorten files
#		ttaenc (http://www.true-audio.com/)
#			used to decompress TTA (True Audio) files
#		wvunpack (http://www.wavpack.com/)
#			used to decompress WavPack files
#		ffmpeg (http://www.ffmpeg.org/)
#			used to decompress MLP, TAK, and lossles WMA files
#			optionally used to decompress ALAC, APE, Shorten, and WavPack files
#
#	Please visit the application's homepage for additional information.
#
# -----------------------------------------------------------------------------

# Static variables
readonly VERSION="2.1.5"
readonly PROG=$(basename $0)

# Setup environment
TMP='/tmp'
DELETE=''
OVERWRITE=''
USEFFMPEG=''
COMPRESS=8
THREADS=1
COPYTAGS=1
KEEPFOREIGN=''
FILES=()
COLOR='\E[33;40m\033[1m' #comment these out if your term doesn't support colors
COLORWARN='\E[31;40m\033[1m'
IFS='@'

# Function to display usage information
function warning() {
	echo -ne "Usage: $PROG [-h] [-V] [-d|-m|-p] [-f] [-tN] [-n] [-o] [-cN]\n"
	echo -ne "       $(printf "%${#PROG}s") <filename> [<file2> ...]\n"
	echo -ne "Convert losslessly compressed audio files to FLAC format, preserving tags\n"
	echo -ne "\nOptions:\n"
	echo -ne "   -h   Display this help information\n"
	echo -ne "   -V   Display version and exit\n"
	echo -ne "   -d   Delete file after conversion\n"
	echo -ne "   -m   Move file to trash after conversion\n"
	echo -ne "   -p   Prompt to delete file after conversion\n"
	echo -ne "   -f   Use ffmpeg instead of default utilities to decode input files\n"
	echo -ne "        Note: Existing tags will not be copied if ffmpeg is used\n"
	echo -ne "   -tN  Convert N number of files concurrently; default is 1\n"
	echo -ne "   -n   Do not copy existing tags to new FLAC file\n"
	echo -ne "   -k   Keep foreign metadata not natively supported by FLAC\n"
	echo -ne "   -o   Overwrite existing output FLAC files\n"
	echo -ne "   -cN  Set FLAC compression level, where N = 0 (fast) - 8 (best); default is 8\n"
	echo -ne "\nSupported input formats:\n"
	echo -ne "   Apple Lossless (.m4a)\n"
	echo -ne "   FLAC (.flac)\n"
	echo -ne "   Monkey's Audio (.ape)\n"
	echo -ne "   Shorten (.shn)\n"
	echo -ne "   True Audio (.tta)\n"
	echo -ne "   WAV (.wav)\n"
	echo -ne "   WavPack (.wv)\n"
	echo -ne "\nSupported ffmpeg-only input formats:\n"
	echo -ne "   Meridian Lossless Packing (.mlp)\n"
	echo -ne "   Tom's lossless Audio Kompressor (TAK)\n"
	echo -ne "   Windows Media Audio Lossless (.wma)\n"
	exit
}

# Function to display colorized output
function cecho () {
	MESSAGE=${1:-"Error: No message passed"}
	echo -e "${COLOR}${MESSAGE}"
	tput sgr0
}

# Function to display colorized warnings
function cwarn () {
	MESSAGE=${1:-"Error: No message passed"}
	echo -e "${COLORWARN}${MESSAGE}"
	tput sgr0
}

# Function to determine if variable is an integer
function is_int() {
	return $(test "$1" -eq "$1" > /dev/null 2>&1);
}

# Function to check for ffmpeg binary
function ffmpeg_check() {
	FFMPEG=$(which ffmpeg 2>/dev/null)
	if [ ! -e "$FFMPEG" ]; then
		echo "Error: cannot find ffmpeg binary"
		MISSING=true
	fi
}

# Function to verify that necessary support binaries exist
function bincheck() {
	MISSING=''
	case $EXT in
		"ape")
			MAC=$(which mac 2>/dev/null)
			APEINFO=$(which apeinfo 2>/dev/null)
			if [ -n "$USEFFMPEG" ]; then
				ffmpeg_check
			else
				[ ! -e "$MAC" ] && MISSING+='mac, '
				[[ -n "$COPYTAGS" && ! -e "$APEINFO" ]] && MISSING+="apeinfo (optional with '-n'), "
			fi
		;;
		"flac")
			if [ -n "$USEFFMPEG" ]; then
				echo "Warning: ffmpeg is not used for FLAC (.flac) files"
			fi
		;;
		"m4a")
			ALAC=$(which alac 2>/dev/null)
			MP4INFO=$(which mp4info 2>/dev/null)
			if [ -n "$USEFFMPEG" ]; then
				ffmpeg_check
			else
				[ ! -e "$ALAC" ] && MISSING+='alac, '
				[[ -n "$COPYTAGS" && ! -e "$MP4INFO" ]] && MISSING+="mp4info (optional with '-n'), "
			fi
		;;
		"mlp")
			USEFFMPEG=true
			COPYTAGS=''
			ffmpeg_check
		;;
		"shn")
			SHORTEN=$(which shorten 2>/dev/null)
			if [ -n "$USEFFMPEG" ]; then
				ffmpeg_check
			elif [ ! -e "$SHORTEN" ]; then
				MISSING+='shorten, '
			fi
		;;
		"tak")
			USEFFMPEG=true
			COPYTAGS=''
			ffmpeg_check
		;;
		"tta")
			TTAENC=$(which ttaenc 2>/dev/null)
			if [ ! -e "$TTAENC" ]; then
				if [ -n "$USEFFMPEG" ]; then
					MISSING+='ttaenc (ffmpeg does not support True Audio (.tta) files), '
				else
					MISSING+='ttaenc, '
				fi
			elif [ -n "$USEFFMPEG" ]; then
				echo "Warning: ffmpeg is not used for True Audio (.tta) files"
			fi
		;;
		"wav")
			if [ -n "$USEFFMPEG" ]; then
				echo "Warning: ffmpeg is not used for WAV (.wav) files"
			fi
		;;
		"wv")
			WVUNPACK=$(which wvunpack 2>/dev/null)
			if [ -n "$USEFFMPEG" ]; then
				ffmpeg_check
			elif [ ! -e "$WVUNPACK" ]; then
				MISSING+='wvunpack, '
			fi
		;;
		"wma")
			USEFFMPEG=true
			COPYTAGS=''
			ffmpeg_check
		;;
	esac
	if [ -n "$MISSING" ]; then
		echo "Error: cannot find the following binaries: ${MISSING%%, }"
		exit
	fi
}

# Function to parse mp4info output to find tags and convert to VORBISCOMMENT
function mp4tags() {
	TAGS2=${TAGS}.alac
	$SED -i "/ \w*: /w${TAGS2}" $TAGS
	$SED -i "s/^ //" $TAGS2
	$SED -i "s/: /=/" $TAGS2
	$SED -i "s/ of [0-9]\+//" $TAGS2
	$SED -i "s/\(.*\)=/\U\1=/" $TAGS2
	$SED -i "s/TRACK=/TRACKNUMBER=/;s/YEAR=/DATE=/;s/COMMENTS=/DESCRIPTION=/;s/DISK=/DISCNUMBER=/" $TAGS2
	mv $TAGS2 $TAGS
}

# Function to parse wvunpack output to find tags and convert to VORBISCOMMENT
function wvtags() {
	TAGS2=${TAGS}.wv
	$SED -i "/ = /w${TAGS2}" $TAGS
	$SED -i "s/ = /=/" $TAGS2
	$SED -i "s/\(.*\)=/\U\1=/" $TAGS2
	$SED -i "s/TRACK=/TRACKNUMBER=/;s/YEAR=/DATE=/;s/COMMENT=/DESCRIPTION=/;s/DISK=/DISCNUMBER=/" $TAGS2
	mv $TAGS2 $TAGS
}

# Function to copy tags for supported formats
function processtags() {
	OUTPUT="\nCopying tags for '$FILE'..."
	TAGS=/tmp/$PROG.$RANDOM.tags
	if [ "$EXT" == "ape" ]; then
		$APEINFO -t "$FILE" >$TAGS
	elif [ "$EXT" == "flac" ]; then
		$METAFLAC --export-tags-to=$TAGS "$FILE"
	elif [ "$EXT" == "m4a" ]; then
		$MP4INFO "$FILE" >$TAGS
		mp4tags
	elif [ "$EXT" == "wv" ]; then
		$WVUNPACK -qss "$FILE" >$TAGS
		wvtags
	else
		OUTPUT+="  tags not supported by for this format\n"
		return
	fi
	if [[ $? -ne 0 || ! -s "$TAGS" ]]; then
		OUTPUT+="\nWarning: tags could not be read from \"$FILE\"\n"
	else
		$METAFLAC --import-tags-from=$TAGS "$NAME.flac"
		if [[ $? -ne 0 ]]; then
			OUTPUT+="\nWarning: tags could not be written to \"$NAME.flac\"\n"
		else
			OUTPUT+="  complete\n"
		fi
	fi
	rm $TAGS
	echo -ne "$OUTPUT"
}

# Function to perform actual transcoding
function transcode() {
	QUIET=''

	# Use ffmpeg, if requested, to decode input
	if [ -n "$USEFFMPEG" ] && [ "$EXT" == "ape" -o "$EXT" == "m4a" -o "$EXT" == "mlp" -o "$EXT" == "shn" -o "$EXT" == "tak" -o "$EXT" == "wv" -o "$EXT" == "wma" ]; then

		# If WMA, additionally verify file is lossless before continuing
		if [ "$EXT" == "wma" \
			-a $($FFMPEG -i "$FILE" 2>&1 | grep 'Stream.*Audio:' | grep wmalossless | wc -l) -lt 1 ]; then
			cwarn "\nError: \"$FILE\" is a lossy WMA.  This should not be converted to FLAC."
			exit 1
		fi

		WAVENAME="/tmp/$(basename $NAME).wav"
		[ $THREADS -gt 1 ] && QUIET='2>/dev/null'
		[ "$EXT" == "mlp" ] && CODEC='-acodec pcm_s24le' || CODEC=
		eval $FFMPEG -i \"$FILE\" $CODEC -f wav \"$WAVENAME.wav\" $QUIET
		if [ $? -ne 0 ]; then
			cwarn "\nError: \"$FILE\" could not be converted to a FLAC file."
			rm "$WAVENAME.wav"
			exit 1
		fi
		eval $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -o \"$NAME.flac\" \"$WAVENAME.wav\" $QUIET
		if [ $? -ne 0 ]; then
			cwarn "\nError: \"$FILE\" could not be converted to a FLAC file."
			rm "$WAVENAME.wav"
			exit 1
		fi
		rm "$WAVENAME.wav"

	# Otherwise, use dedicated binaries for decoding
	else

		# Monkey's Audio input
		if [ "$EXT" == "ape" ]; then
			[ $THREADS -gt 1 ] && QUIET='2>/dev/null'
			eval $MAC \"$FILE\" - -d $QUIET | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -s -o "$NAME.flac" -

		# FLAC input
		elif [ "$EXT" == "flac" ]; then
			# Original FLAC file needs to be renamed
			if [[ -e "${NAME}_old.flac" ]]; then
				if [ $OVERWRITE ]; then
					mv -i "$FILE" "${NAME}_old.flac"
				else
					echo -e "Error: '${NAME}_old.flac' already exists: could not rename input file"
					exit 1
				fi
			else
				mv -i "$FILE" "${NAME}_old.flac"
			fi
			FILE="${NAME}_old.flac"
			[ $THREADS -gt 1 ] && QUIET='-s'
			$FLAC -d "$FILE" $QUIET -c | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -s -o "$NAME.flac" -

		# ALAC input
		elif [ "$EXT" == "m4a" ]; then
			$ALAC -t "$FILE"
			# .m4a is not a unique extension, so first verify the format
			if [ $? -ne 0 ]; then
				echo "ERROR: '$FILE' is not a valid ALAC file"
				exit 1
			fi
			[ $THREADS -gt 1 ] && QUIET='-s'
			$ALAC "$FILE" | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE $QUIET -o "$NAME.flac" -

		# Shorten input
		elif [ "$EXT" == "shn" ]; then
			[ $THREADS -gt 1 ] && QUIET='-s'
			$SHORTEN -x "$FILE" - | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE $QUIET -o "$NAME.flac" -

		# True Audio input
		elif [ "$EXT" == "tta" ]; then
			[ $THREADS -gt 1 ] && QUIET='2>/dev/null'
			eval $TTAENC -d -o - \"$FILE\" $QUIET | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -s -o "$NAME.flac" -

		# WAVE input
		elif [ "$EXT" == "wav" ]; then
			[ $THREADS -gt 1 ] && QUIET='-s'
			$FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE $QUIET -o "$NAME.flac" "$FILE"

		# WavPack input
		elif [ "$EXT" == "wv" ]; then
			[ $THREADS -gt 1 ] && QUIET='-q'
			$WVUNPACK $QUIET "$FILE" -o - | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -s -o "$NAME.flac" -
		fi
	fi

	# Abort if transcode failed
	if [ ${PIPESTATUS[0]} -ne 0 ]; then
		cwarn "\nError: \"$FILE\" could not be converted to a FLAC file."
		if [[ "$EXT" == "flac" ]]; then
			cwarn "Restoring _old file to original name.\n"
			mv "$FILE" "$NAME.flac"
		fi
		exit 1
	fi

	# Copy metadata to transcoded file, but not for ffmpeg decoding
	if [ $COPYTAGS ]; then
		processtags
	fi

	# Delete old file if requested
	if [ "$DELETE" == "prompt" ]; then
		echo -ne "\nDelete \"$FILE\"? "
		read -e DELPROMPT
		if [[ "$DELPROMPT" == "y" || "$DELPROMPT" == "Y" ]]; then
			DELETE=force
		fi
	fi
	OUTPUT="\nConversion complete - "
	if [ "$DELETE" == "force" ]; then
		rm "$FILE"
		OUTPUT+="deleted"
	elif [ "$DELETE" == "move" ]; then
		$TPUT "$FILE"
		OUTPUT+="trashed"
	else
		OUTPUT+="kept"
	fi
	OUTPUT+=" \"$FILE\"\n\n"
	echo -ne "$OUTPUT"
}

# Process arguments
if [[ $# -eq 0 ]]; then
	warning
else
	while [ $# -ne 0 ]; do

		# Match known arguments
		if [ "$1" == "-h" ]; then
			warning
		elif [ "$1" == "-V" ]; then
			echo "Version $VERSION"
			exit
		elif [ "$1" == "-d" ]; then
			if [ "$DELETE" == "" ]; then
				DELETE="force"
			else
				echo "Error: Only one deletion option (-d, -m, -p) can be specified)"
				exit
			fi
		elif [ "$1" == "-m" ]; then
			if [ "$DELETE" == "" ]; then
				DELETE="move"
			else
				echo "Error: Only one deletion option (-d, -m, -p) can be specified)"
				exit
			fi
		elif [ "$1" == "-p" ]; then
			if [ $THREADS -gt 1 ]; then
				echo "Error: The -p and -t options cannot be used together"
				exit
			fi
			if [ "$DELETE" == "" ]; then
				DELETE="prompt"
			else
				echo "Error: Only one deletion option (-d, -m, -p) can be specified)"
				exit
			fi
		elif [ "${1:0:2}" == "-c" ]; then
			COMPRESS=${1:2}
			is_int "$COMPRESS"
			if [ $? -ne 0 ] || [ $COMPRESS -lt 0 -o $COMPRESS -gt 8 ]; then
				echo "Error: You must specify a number between 0-8 for compression (-cN)"
				exit
			fi
		elif [ "${1:0:2}" == "-t" ]; then
			PROCS=$(grep -c processor /proc/cpuinfo)
			THREADS=${1:2}
			is_int "$THREADS"
			if [ $? -ne 0 ] || [ $THREADS -lt 1 ]; then
				echo "Error: You must specify the number of threads (-tN)"
				exit
			elif [ ${1:2} -gt $PROCS ]; then
				echo "You specified $THREADS threads, but you only have $PROCS processors."
				echo "Please specify no more than $PROCS threads."
				exit
			elif [ "$DELETE" == "prompt" -a $THREADS -gt 1 ]; then
				echo "Error: The -p and -t options cannot be used together"
				exit
			fi
		elif [ "$1" == "-n" ]; then
			COPYTAGS=''
		elif [ "$1" == "-k" ]; then
			KEEPFOREIGN='--keep-foreign-metadata'
		elif [ "$1" == "-o" ]; then
			OVERWRITE='-f'
		elif [ "$1" == "-f" ]; then
			USEFFMPEG=true
			COPYTAGS=''

		# Anything that's not a known argument gets treated as a file
		else
			FILES[${#FILES[*]}]=$1
		fi
		shift
	done
fi

# Validate COMPRESS setting
if [[ "$COMPRESS" != [0-8] ]]; then
	echo "Error: FLAC compression level must be between 0 and 8"
	exit
fi

# Define and verify core apps exist
SED=$(which sed 2>/dev/null)
FLAC=$(which flac 2>/dev/null)
METAFLAC=$(which metaflac 2>/dev/null)
TPUT=$(which trash-put 2>/dev/null)
MISSING=''
[ ! -e "$SED" ] && MISSING+='sed, '
[ ! -e "$FLAC" ] && MISSING+='flac, '
[ ! -e "$METAFLAC" ] && MISSING+='metaflac, '
[ "$DELETE" == "move" -a ! -e "$TPUT" ] && MISSING+='trash-put, '
if [ -n "$MISSING" ]; then
	echo "Error: cannot find the following binaries: ${MISSING%%, }"
	exit
fi


# Process each passed file sequentially
for FILE in ${FILES[@]}; do
	# Verify file exists
	if [ ! -e "$FILE" ]; then
		echo "Error: '$FILE' does not exist"
		exit 1
	fi

	# Determine file type and base filename
	NAME=${FILE%.*}
	EXT=$(echo "${FILE##*.}" | $SED 's/\(.*\)/\L\1/')

	# Exit if wrong file passed
	if [[ "$EXT" != "ape" && "$EXT" != "flac" && "$EXT" != "m4a" && "$EXT" != "mlp" && "$EXT" != "shn" && "$EXT" != "tak" && "$EXT" != "tta" && "$EXT" != "wav" && "$EXT" != "wv" && "$EXT" != "wma" ]]; then
		echo "Error: '$FILE' is not a supported input format"
		exit 1
	fi

	# Verify support binaries
	bincheck

	# Transcode file, concurrently up to number of specified threads
	cecho "\nProcessing '$FILE'...\n"
	if [ $(jobs | wc -l) -lt $THREADS ]; then
		transcode &
	fi
	while [ $(jobs | wc -l) -ge $THREADS ]; do
		sleep 0.1
		jobs >/dev/null
	done
done

# Wait for any remaining processes to finish before exiting
wait

User avatar
Head_on_a_Stick
Posts: 13450
Joined: 2014-06-01 17:46
Location: /dev/chair

Re: Simple question about bash

#5 Post by Head_on_a_Stick »

pythagorasmk wrote:I get the error message from ffmpeg that */*.m4a does not exist
Can we see the exact message? Your line looks okay to me.
Bloom wrote:a very good Bash script
Not according to https://www.shellcheck.net/:

Code: Select all

Line 55:
readonly PROG=$(basename $0)
                         ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
readonly PROG=$(basename "$0")
 
Line 58:
TMP='/tmp'
^-- SC2034: TMP appears unused. Verify use (or export if used externally).
 
Line 120:
   return $(test "$1" -eq "$1" > /dev/null 2>&1);
          ^-- SC2046: Quote this to prevent word splitting.
                               ^-- SC2065: This is interpreted as a shell file redirection, not a comparison.
 
Line 219:
   $SED -i "/ \w*: /w${TAGS2}" $TAGS
                               ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "/ \w*: /w${TAGS2}" "$TAGS"
 
Line 220:
   $SED -i "s/^ //" $TAGS2
                    ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "s/^ //" "$TAGS2"
 
Line 221:
   $SED -i "s/: /=/" $TAGS2
                     ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "s/: /=/" "$TAGS2"
 
Line 222:
   $SED -i "s/ of [0-9]\+//" $TAGS2
                             ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "s/ of [0-9]\+//" "$TAGS2"
 
Line 223:
   $SED -i "s/\(.*\)=/\U\1=/" $TAGS2
                              ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "s/\(.*\)=/\U\1=/" "$TAGS2"
 
Line 224:
   $SED -i "s/TRACK=/TRACKNUMBER=/;s/YEAR=/DATE=/;s/COMMENTS=/DESCRIPTION=/;s/DISK=/DISCNUMBER=/" $TAGS2
>>                                                                                                ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "s/TRACK=/TRACKNUMBER=/;s/YEAR=/DATE=/;s/COMMENTS=/DESCRIPTION=/;s/DISK=/DISCNUMBER=/" "$TAGS2"
 
Line 225:
   mv $TAGS2 $TAGS
      ^-- SC2086: Double quote to prevent globbing and word splitting.
             ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   mv "$TAGS2" "$TAGS"
 
Line 231:
   $SED -i "/ = /w${TAGS2}" $TAGS
                            ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "/ = /w${TAGS2}" "$TAGS"
 
Line 232:
   $SED -i "s/ = /=/" $TAGS2
                      ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "s/ = /=/" "$TAGS2"
 
Line 233:
   $SED -i "s/\(.*\)=/\U\1=/" $TAGS2
                              ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "s/\(.*\)=/\U\1=/" "$TAGS2"
 
Line 234:
   $SED -i "s/TRACK=/TRACKNUMBER=/;s/YEAR=/DATE=/;s/COMMENT=/DESCRIPTION=/;s/DISK=/DISCNUMBER=/" $TAGS2
>>                                                                                               ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   $SED -i "s/TRACK=/TRACKNUMBER=/;s/YEAR=/DATE=/;s/COMMENT=/DESCRIPTION=/;s/DISK=/DISCNUMBER=/" "$TAGS2"
 
Line 235:
   mv $TAGS2 $TAGS
      ^-- SC2086: Double quote to prevent globbing and word splitting.
             ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   mv "$TAGS2" "$TAGS"
 
Line 243:
      $APEINFO -t "$FILE" >$TAGS
                           ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
      $APEINFO -t "$FILE" >"$TAGS"
 
Line 245:
      $METAFLAC --export-tags-to=$TAGS "$FILE"
                                 ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
      $METAFLAC --export-tags-to="$TAGS" "$FILE"
 
Line 247:
      $MP4INFO "$FILE" >$TAGS
                        ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
      $MP4INFO "$FILE" >"$TAGS"
 
Line 250:
      $WVUNPACK -qss "$FILE" >$TAGS
                              ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
      $WVUNPACK -qss "$FILE" >"$TAGS"
 
Line 256:
   if [[ $? -ne 0 || ! -s "$TAGS" ]]; then
         ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
 
Line 259:
      $METAFLAC --import-tags-from=$TAGS "$NAME.flac"
                                   ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
      $METAFLAC --import-tags-from="$TAGS" "$NAME.flac"
 
Line 260:
      if [[ $? -ne 0 ]]; then
            ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
 
Line 266:
   rm $TAGS
      ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   rm "$TAGS"
 
Line 275:
   if [ -n "$USEFFMPEG" ] && [ "$EXT" == "ape" -o "$EXT" == "m4a" -o "$EXT" == "mlp" -o "$EXT" == "shn" -o "$EXT" == "tak" -o "$EXT" == "wv" -o "$EXT" == "wma" ]; then
                                               ^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
>>                                                                ^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
>>                                                                                   ^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
>>                                                                                                      ^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
>>                                                                                                                         ^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
>>                                                                                                                                           ^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
 
Line 279:
         -a $($FFMPEG -i "$FILE" 2>&1 | grep 'Stream.*Audio:' | grep wmalossless | wc -l) -lt 1 ]; then
         ^-- SC2166: Prefer [ p ] && [ q ] as [ p -a q ] is not well defined.
            ^-- SC2046: Quote this to prevent word splitting.
>>                                                              ^-- SC2126: Consider using grep -c instead of grep|wc -l.
 
Line 284:
      WAVENAME="/tmp/$(basename $NAME).wav"
                                ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
      WAVENAME="/tmp/$(basename "$NAME").wav"
 
Line 287:
      eval $FFMPEG -i \"$FILE\" $CODEC -f wav \"$WAVENAME.wav\" $QUIET
           ^-- SC2086: Double quote to prevent globbing and word splitting.
                        ^-- SC2086: Double quote to prevent globbing and word splitting.
                                ^-- SC2086: Double quote to prevent globbing and word splitting.
                                                ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
      eval "$FFMPEG" -i \""$FILE"\" "$CODEC" -f wav \""$WAVENAME".wav\" $QUIET
 
Line 288:
      if [ $? -ne 0 ]; then
           ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
 
Line 293:
      eval $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -o \"$NAME.flac\" \"$WAVENAME.wav\" $QUIET
           ^-- SC2086: Double quote to prevent globbing and word splitting.
                            ^-- SC2086: Double quote to prevent globbing and word splitting.
                                         ^-- SC2086: Double quote to prevent globbing and word splitting.
                                                         ^-- SC2086: Double quote to prevent globbing and word splitting.
>>                                                                      ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
      eval "$FLAC" -$COMPRESS "$KEEPFOREIGN" "$OVERWRITE" -o \""$NAME".flac\" \""$WAVENAME".wav\" $QUIET
 
Line 294:
      if [ $? -ne 0 ]; then
           ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
 
Line 307:
         eval $MAC \"$FILE\" - -d $QUIET | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -s -o "$NAME.flac" -
              ^-- SC2086: Double quote to prevent globbing and word splitting.
                     ^-- SC2086: Double quote to prevent globbing and word splitting.
>>                                                          ^-- SC2086: Double quote to prevent globbing and word splitting.
>>                                                                       ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         eval "$MAC" \""$FILE"\" - -d $QUIET | $FLAC -$COMPRESS "$KEEPFOREIGN" "$OVERWRITE" -s -o "$NAME.flac" -
 
Line 313:
            if [ $OVERWRITE ]; then
                 ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
            if [ "$OVERWRITE" ]; then
 
Line 324:
         $FLAC -d "$FILE" $QUIET -c | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -s -o "$NAME.flac" -
                                                       ^-- SC2086: Double quote to prevent globbing and word splitting.
>>                                                                  ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         $FLAC -d "$FILE" $QUIET -c | $FLAC -$COMPRESS "$KEEPFOREIGN" "$OVERWRITE" -s -o "$NAME.flac" -
 
Line 330:
         if [ $? -ne 0 ]; then
              ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
 
Line 335:
         $ALAC "$FILE" | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE $QUIET -o "$NAME.flac" -
                                          ^-- SC2086: Double quote to prevent globbing and word splitting.
                                                       ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         $ALAC "$FILE" | $FLAC -$COMPRESS "$KEEPFOREIGN" "$OVERWRITE" $QUIET -o "$NAME.flac" -
 
Line 340:
         $SHORTEN -x "$FILE" - | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE $QUIET -o "$NAME.flac" -
                                                  ^-- SC2086: Double quote to prevent globbing and word splitting.
>>                                                             ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         $SHORTEN -x "$FILE" - | $FLAC -$COMPRESS "$KEEPFOREIGN" "$OVERWRITE" $QUIET -o "$NAME.flac" -
 
Line 345:
         eval $TTAENC -d -o - \"$FILE\" $QUIET | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -s -o "$NAME.flac" -
              ^-- SC2086: Double quote to prevent globbing and word splitting.
                                ^-- SC2086: Double quote to prevent globbing and word splitting.
>>                                                                ^-- SC2086: Double quote to prevent globbing and word splitting.
>>                                                                             ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         eval "$TTAENC" -d -o - \""$FILE"\" $QUIET | $FLAC -$COMPRESS "$KEEPFOREIGN" "$OVERWRITE" -s -o "$NAME.flac" -
 
Line 350:
         $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE $QUIET -o "$NAME.flac" "$FILE"
                          ^-- SC2086: Double quote to prevent globbing and word splitting.
                                       ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         $FLAC -$COMPRESS "$KEEPFOREIGN" "$OVERWRITE" $QUIET -o "$NAME.flac" "$FILE"
 
Line 355:
         $WVUNPACK $QUIET "$FILE" -o - | $FLAC -$COMPRESS $KEEPFOREIGN $OVERWRITE -s -o "$NAME.flac" -
                                                          ^-- SC2086: Double quote to prevent globbing and word splitting.
>>                                                                     ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         $WVUNPACK $QUIET "$FILE" -o - | $FLAC -$COMPRESS "$KEEPFOREIGN" "$OVERWRITE" -s -o "$NAME.flac" -
 
Line 360:
   if [ ${PIPESTATUS[0]} -ne 0 ]; then
        ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   if [ "${PIPESTATUS[0]}" -ne 0 ]; then
 
Line 370:
   if [ $COPYTAGS ]; then
        ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   if [ "$COPYTAGS" ]; then
 
Line 377:
      read -e DELPROMPT
      ^-- SC2162: read without -r will mangle backslashes.
 
Line 436:
         if [ $? -ne 0 ] || [ $COMPRESS -lt 0 -o $COMPRESS -gt 8 ]; then
              ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
                              ^-- SC2086: Double quote to prevent globbing and word splitting.
                                              ^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
                                                 ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         if [ $? -ne 0 ] || [ "$COMPRESS" -lt 0 -o "$COMPRESS" -gt 8 ]; then
 
Line 444:
         if [ $? -ne 0 ] || [ $THREADS -lt 1 ]; then
              ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
                              ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         if [ $? -ne 0 ] || [ "$THREADS" -lt 1 ]; then
 
Line 447:
         elif [ ${1:2} -gt $PROCS ]; then
                ^-- SC2086: Double quote to prevent globbing and word splitting.
                           ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         elif [ "${1:2}" -gt "$PROCS" ]; then
 
Line 451:
         elif [ "$DELETE" == "prompt" -a $THREADS -gt 1 ]; then
                                      ^-- SC2166: Prefer [ p ] && [ q ] as [ p -a q ] is not well defined.
                                         ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
         elif [ "$DELETE" == "prompt" -a "$THREADS" -gt 1 ]; then
 
Line 488:
[ "$DELETE" == "move" -a ! -e "$TPUT" ] && MISSING+='trash-put, '
                      ^-- SC2166: Prefer [ p ] && [ q ] as [ p -a q ] is not well defined.
 
Line 496:
for FILE in ${FILES[@]}; do
            ^-- SC2068: Double quote array expansions to avoid re-splitting elements.
 
Line 518:
   if [ $(jobs | wc -l) -lt $THREADS ]; then
        ^-- SC2046: Quote this to prevent word splitting.
                            ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   if [ $(jobs | wc -l) -lt "$THREADS" ]; then
 
Line 521:
   while [ $(jobs | wc -l) -ge $THREADS ]; do
           ^-- SC2046: Quote this to prevent word splitting.
                               ^-- SC2086: Double quote to prevent globbing and word splitting.

Did you mean: (apply this, apply all SC2086)
   while [ $(jobs | wc -l) -ge "$THREADS" ]; do
Looks like Jared Breland needs to learn about quoting and a few other things.
Black Lives Matter

Debian buster-backports ISO image: for new hardware support

pythagorasmk
Posts: 117
Joined: 2015-01-18 03:40

Re: Simple question about bash

#6 Post by pythagorasmk »

Head_on_a_Stick wrote:
pythagorasmk wrote:I get the error message from ffmpeg that */*.m4a does not exist
Can we see the exact message? Your line looks okay to me.
The line is OK, except that the ${i%m4a}wav should be in double quotes.
Could you give me example how this job can be done by find command. I want to learn new things. Thanks.

User avatar
Head_on_a_Stick
Posts: 13450
Joined: 2014-06-01 17:46
Location: /dev/chair

Re: Simple question about bash

#7 Post by Head_on_a_Stick »

pythagorasmk wrote:Could you give me example how this job can be done by find command
Something like this run from the directory containing the albums:

Code: Select all

find . -name "*.m4a" -exec ffmpeg -i {} $(basename {} m4a)wav \;
(Untested)
Black Lives Matter

Debian buster-backports ISO image: for new hardware support

Post Reply