ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
#list.sh
#!/bin/sh
list="$(ls *mp3)"
n=0
for file in $list
do
v[n]="$file"
let n=n+1
done
n=0
until [ -z "$1" ]
do
echo "${v[$1]}"
shift
let n=n+1
done
exit
This script takes an argument n and prints the name of the n+1 th file in the current directory. If given several arguments, for example
Code:
$ list.sh 0 3 4
it prints the 1st, 4th and 5th filename in the directory. The problem is that there may be spaces in the filenames. If the 1st file is "john smith", then 'list.sh 1' will not print the 2nd file name but "smith". The problem is in the first half of the script, the repeat block can be disregarded. How can I solve this?
One option may be to read the list of files directly into an array with one file per line:
Code:
IFS=$'\n'
list=($(ls -1 *.mp3))
# or use $(find ~/mp3folder/ -iname '*.mp3' -print) for a recursive search
IFS=''
n=0
for file in "${list[@]}"
do
echo "$file"
((n++))
done
Thank you very much. The links solved the problem. Could I ask you how to determine, within a bash script, if a certain string contains a given substring. For example, given "superior" I want to know it if contains "upe", which here is certainly true.
More precisely, the problem is this: one of the arguments can be of the form m-n, for example,
Code:
list.sh 2 4 6-8
The program would have to know the last argument contains a hyphen (it means play from 6 up to 8) and get the 6 and the 8. Is this very difficult? Once the presence of the hyphen is detected, perhaps sed could extract m and n.
You can try the pattern matching operator =~. In order to match a numeric interval, looking for an hyphen is not enough, otherwise strings like "-8" or "hello-world" or "6-" would be valid. Instead you have to match the numbers as well:
Code:
[[ $1 =~ ^[0-9]+-[0-9]+$ ]] && echo "$1 is a numeric interval"
Having now a blank separator between the two numbers I guess it would be easy to put each one in a separate variable, though I do not immediately see how to do it.
# play.sh
# Example: play.sh 0 3-5 8
# Play 1st, 4th, 5th, 6th and 9th files in current directory.
#!/bin/sh
n=0
for file in *mp3
do
v[n]="$file"
let n=n+1
done
n=0
until [ -z "$1" ]
do
if [[ $1 =~ ^[0-9]+-[0-9]+$ ]] # Thanks colucix
then
# $1 is an interval m-n
int=$1
# Split "m-n" in "m" and "n"
n1="${int%-*}" # Get m
n2="${int##*-}" # Get n
# Process from v[n1] up to v[n2]
for (( i=$n1; i <= $n2; i++ )); do
mplayer "${v[i]}"
done
else
mplayer "${v[$1]}"
fi
shift
let n=n+1
done
exit
Now you have a solution .. here is another way to think about
Code:
#!/bin/bash
files=( *.mp3 )
for f
do
if [[ $f =~ - ]]
then
for (( i = ${f%-*}; i < ${f#*-}; i++ ))
do
mplayer "${files[i]}"
done
f=${f#*-}
fi
mplayer "${files[f]}"
done
I would probably add in a test to make sure that the directory where you run this actually has mp3 files, ie test if array empty.
Many others of course ... just thought it might interest you.
If I press ^C while the script is running it has no other effect than making mplayer go on to the next song. How could I stop the program in response to ^C or some other key?
One option may be to read the list of files directly into an array with one file per line:
Code:
IFS=$'\n'
list=($(ls -1 *.mp3))
# or use $(find ~/mp3folder/ -iname '*.mp3' -print) for a recursive search
IFS=''
n=0
for file in "${list[@]}"
do
echo "$file"
((n++))
done
No. This is incorrect. File names can have new line characters in them.
Quote:
Originally Posted by stf92
More precisely, the problem is this: one of the arguments can be of the form m-n, for example,
Code:
list.sh 2 4 6-8
Code:
foo=6-8
range=false
case $foo in
*-*-*)
echo "$foo: invalid argument" >&2
exit 1
;;
?*-?*)
foo1=${foo%-*}
foo2=${foo#*-}
;;
*-*)
echo "$foo: invalid argument" >&2
exit 1
esac
if $range; then
: use $foo1 and $foo2
else
: use $foo
fi
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.