0

I am creating a script called "convert_mkv_mp4_v3.sh"

#!/bin/bash
# If no directory is given, work in local dir
if [ "$1" = "" ]; then
  DIR=.
else
  DIR="$1"
fi

arrayname=()
while IFS= read -d '' -r filename; do
    arrayname+=("$filename")
done < <(find ${DIR} -name '*.mkv' -print0)
printf "%s\n" "${arrayname[@]}"

When I run it with: convert_mkv_mp4_v3.sh ./U* it prints 3 file names:

./U2 - Go Home Live from Slane Castle Ireland/title_t00.mkv
./U2 - Go Home Live from Slane Castle Ireland/Scenes/title_t01.mkv
./U2 - Go Home Live from Slane Castle Ireland/Scenes/title_t02.mkv

On the other hand, if I alter the following find ${DIR} -name '*.mkv' -print0 to find ./U* -name '*.mkv' -print0 I get:

./U2 - Go Home Live from Slane Castle Ireland/title_t00.mkv
./U2 - Go Home Live from Slane Castle Ireland/Scenes/title_t01.mkv
./U2 - Go Home Live from Slane Castle Ireland/Scenes/title_t02.mkv
./U2 - Live/U2 - Live - Germany 1983.mkv
./U2 - Rattle and Hum/title_t00.mkv
./U2 - The Best of 1990-2000/U2 - The Best of 1990-2000 - video.mkv
./U2 - The Best of 1990-2000/Scenes/U2 - The Best of 1990-2000 - extra.mkv
./U2 - The Joshua Tree/title_t00.mkv
./U2 - Vertigo 2006 - Sao Paulo/title_t00.mkv
./U2 - Zoo TV live from Sydney/title_t00.mkv
./Ultraje a Rigor - Acustico MTV/Scenes/title_t06.mkv
./Ultraje a Rigor - Acustico MTV/Scenes/title_t01.mkv
./Ultraje a Rigor - Acustico MTV/Scenes/title_t02.mkv
./Ultraje a Rigor - Acustico MTV/Scenes/title_t05.mkv
./Ultraje a Rigor - Acustico MTV/Scenes/title_t04.mkv
./Ultraje a Rigor - Acustico MTV/Scenes/title_t03.mkv
./Ultraje a Rigor - Acustico MTV/title_t00.mkv

Could someone help me to understand what is happening and how to fix it?

RG

rnng
  • 1
  • 1
    a little aside: with `dir=${1:-.}` you can get rid of the first `if then else` – Fravadona Jun 21 '22 at 18:08
  • 2
    `./U*` is expanded by the *shell* before the script is executed. `$1` is only the *first* directory that `./U*` expands to, not the literal string `./U*`. – chepner Jun 21 '22 at 18:11
  • An other aside: Are you on bash >= 4.3? if so then you can use `readarray -d '' arrayname < <(find "${dir}" -name '*.mkv' -print0)` instead of the `while` loop – Fravadona Jun 21 '22 at 18:11
  • @Fravadona tried that. In fact while loop is gone, but still getting different results if I use find "${dir}" or find ./U* – rnng Jun 21 '22 at 18:19
  • add echo "$@"` in the script to see what's being passed in from the command line – markp-fuso Jun 21 '22 at 18:24
  • `printf '%s\n' "$@"` is much less ambiguous than `echo "$@"`, if you want to print command line arguments.- – Charles Duffy Jun 21 '22 at 18:27

1 Answers1

3

The shell expands ./U* to multiple directories before the script executes. As a result, the script receives multiple arguments, one per directory. You want something like

#!/bin/bash


arrayname=()
while IFS= read -d '' -r filename; do
    arrayname+=("$filename")
done < <(find "${@:-.}" -name '*.mkv' -print0)
printf "%s\n" "${arrayname[@]}"

If there are arguments, "${@:-.}" expands to a series of individual directory names. If not, then it expands to ..

chepner
  • 497,756
  • 71
  • 530
  • 681