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.
I have a little script which puts the output from ls into an array.
However, it does not work if a file in the directory has a whitespace (or more) in its filename since my script will interpret that line from ls as two lines (or more depending on how many whitespaces their are)
my script (named array) looks like this:
#!/bin/bash
array=(`ls`)
len=${#array[*]}
i=0
while [ $i -lt $len ]; do
echo "$i: ${array[$i]}"
let i++
done
If I do an ls the result is:
[samel@arch bla]$ ls
array foobar
and the output from the script:
[samel@arch bla]$ ./array
0: array
1: foobar
BUT if I rename "foobar" to "foo bar"
the script gives:
[samel@arch bla]$ ./array
0: array
1: foo
2: bar
How should I solve this? I rather not use "ls | sed -ne numer" in a whileloop that puts line by line into the array, I only want to do ls once or so.
I actually intend to put the output from find, and if I do "a find" and it gives some hundreds line I don't want to repeat that every time in a whileloop since it takes a lot of time to get it finished.
IFS is the "Internal Field Separator". It's a character (or list of characters) that bash uses for filename globbing, etc. By putting the quotes a line apart, it includes just a newline. Despite what one would expect, IFS='\n' does NOT work.
oh, the counting was not the thing. I just had len=${#array[*]} to make sure all of the "filenames from ls" got it's own index in the array, so if I had a directory with x files in it, echo $len would output x.
If I had a directory with x files, all with on whitespace in their names, the output from echo $len would be 2x and that's wrong. But now it's solved.
The reason why I want to use this with find, is that I wanted to improve my script that makes a playlist for mplayer. We all know how frustrating it is if you watch a TV-show and one episode is finished and you want to play the next.
With my script (the old one) you go into a directory and type
$playlist episode4.avi
and a playlist will be made from episode4.avi to the last file in the directory.
if [ "x$1" != "x" ]; then
addtoplaylist=false;
else
addtoplaylist=true;
fi
touch playlist.playlist
for (( i=0 ; $i < $length ; i=$i+1 ))
do
line=${playlist[i]}
if [ "x`echo ${playlist[i]} | grep "$1"`" != "x" ]; then
addtoplaylist=true
fi
if [ "x$addtoplaylist" = "xtrue" ]; then
echo ${playlist[i]} >> playlist.playlist
fi
it works fine for my purpose (that is going into a TV-show-episode-x directory since it usually only contains 22 files or so) but if I go into my music directory (I wouldn't really use this script to play my files because there are much better programs for that).
The thing that is taking time in the while-loop is
if [ "x`echo ${playlist[i]} | grep "$1"`" != "x" ]; then
addtoplaylist=true
fi
$1 is the argument you pass to the script. That argument is the file which I want to start to make the playlist from, so it is the file I first want to watch.
If I have
if [ "x${playlist[i]}" = "x$1" ]; then
addtoplaylist=true
fi
then I have to use ./ in my first argument:
$myscript ./episodeiwanttowatch.avi
beacuse all strings in ${playlist} starts with ./
is there another way to tell if $1 is a substring of ${playlist[i]}?
Instead of greping, echoing, and setting addtoplaylist, here is some ways I'd do some things. Of course everyones different, and I'm not too familiar with any standards.
The first part just exits if theres no $1 instead of using and retesting addtoplaylist.
Then use the ${variable/search/replace} ThingeeMaBob (parameter substitution I think?) to strip the ./ off the $1 variable, and the $PLAYLIST array. It won't touch the variables if their is no ./ in them. That way you can use either formats. It's a builtin type deal so should be quick.
Then just send it through those test constructs and you should be good.
I didn't mess around with the IFS in there or anything, just wanted to give a few quick examples you can work with, if you like them.
Code:
#!/bin/bash -x
# Exit if no $1
: ${1?Need a parameter dude}
# Strips ./ off if its there, leaves it alone if it's not.
# Do it here instead of in the loop.
FILENAME=${1/\.\//}
# Get your array of filenames
PLAYLIST=(`find -name "*"`)
# Test constructs the same as if/then/else
for i in ${PLAYLIST[*]/\.\//}; do
[ $FILENAME == $i ] && echo "Yeah, it matches" || echo "No match"
done
Thanks for the help matir but that wasn't what i wanted . What i wanted was:
1. list files in a directory
2. prepend numbers to them
3. Prompt the user which file they want
4. Perform some command based on the input
So, for example...it would spit out:
Code:
1. file.txt
2. file1.txt
3. file2.txt
Which file do you pick?
So, the script will echo "Which file do you pick?" and wait for input. If the user inputs "1", an action will be performed on file.txt. Therefore, I don't know how to write the input that is associated with the filename piece. Thanks...
Thanks guys, I'll check out FILENAME=${1/\.\//}
and see if iy helps me, now I have an ugly hack,
if [ "x${playlist[i]}" = "x$1" -o "x${playlist[i]}" = "x./$1" ]; then ...
it works fine and it doesn't have to be more complicated.
now my script looks like this. It's really fast, it makes a playlist over 300 files in less than 1 second (compared to the 10 second with grepping echos...)
if [ "x$1" != "x" ]; then
addtoplaylist=false;
else
addtoplaylist=true;
fi
touch playlist.playlist
for (( i=0 ; $i < $length ; i=$i+1 ))
do
line=${playlist[i]}
if [ "x${playlist[i]}" = "x$1" -o "x${playlist[i]}" = "x./$1" ]; then
addtoplaylist=true
fi
if [ "x$addtoplaylist" = "xtrue" ]; then
echo ${playlist[i]} >> playlist.playlist
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.