LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-08-2007, 12:07 PM   #1
babag
Member
 
Registered: Aug 2003
Posts: 419

Rep: Reputation: 31
powershell to bash - how to fix this line?


$tmp = Get-ChildItem -name -include $variable*.tga | Sort-Object | Select-Object -first 1

what this does is find the first file of type .tga with a given prefix to
the filename ($variable) in a directory. that file is assigned to $tmp. i'm using it
to find the first file of a group of numbered files that all have a common prefix.
once found, i can process that file and increment the number to process the rest
of the files sequentially.

i'd like to move this script to linux and so will need to adapt it to bash i suppose.

how would this line be adapted to bash?

thanks,
BabaG

Last edited by babag; 06-08-2007 at 12:09 PM.
 
Old 06-08-2007, 12:22 PM   #2
dawkcid
Member
 
Registered: May 2007
Location: UK
Distribution: LFS,Slackware,Slamd64,NetBSD
Posts: 102

Rep: Reputation: 15
It's easier to let the shell handle it, rather than trying to increment the count yourself. Zsh can sort files numerically, but bash can't. However, ls can do so with the -v option. E.g.

Code:
#!/bin/sh

for file in $(ls -v $1*.tga); do
   # process file
done

and call the script with the prefix name. I'm assuming all the files are in the current directory. If not, just wangle a directory in there, e.g.

Code:
...
dir=$1
prefix=$2

for file in $(ls -v $dir/$prefix*.tgz); do
....
Or with zsh (no need to invoke ls):

Code:
#!/bin/zsh

setopt numericglobsort

for file in $1*.tga; do # zsh sorts files automatically
    # process file
done

Last edited by dawkcid; 06-08-2007 at 12:29 PM.
 
Old 06-08-2007, 01:13 PM   #3
babag
Member
 
Registered: Aug 2003
Posts: 419

Original Poster
Rep: Reputation: 31
thanks so much dawkcid. will look into these as soon as i'm back in front of
my linux box.

i was incrementing the files rather than doing a sort each time because i found,
under powershell at least, that the sort was too slow. these are directories of
timelapse still image sequences and have up to 32000 files in them. that being
the case, i found that sorting once to find the first file and then using an
increment routine was much faster than repeated sorts.

thanks again,
BabaG

Last edited by babag; 06-08-2007 at 01:17 PM.
 
Old 06-08-2007, 02:24 PM   #4
babag
Member
 
Registered: Aug 2003
Posts: 419

Original Poster
Rep: Reputation: 31
just thought of this. powershell allows me to find the last file
in the series just by changing the word 'first' to 'last' in the
example in my original post. how would i do this in a bash
script?

thanks,
BabaG
 
Old 06-09-2007, 11:02 AM   #5
dawkcid
Member
 
Registered: May 2007
Location: UK
Distribution: LFS,Slackware,Slamd64,NetBSD
Posts: 102

Rep: Reputation: 15
If you assign the output of ls -v to an array, you can access any element, e.g.

Code:
filelist=($(ls -v $1*.tga))
echo ${filelist[0]} # first element
The syntax for the last element is more verbose than it really needs to be because of bash's stupid syntax. It's more readable to do it in two steps.

Code:
last=$(( ${#filelist[*]} - 1))
echo ${filelist[$last]}
As opposed to most scripting languages like Python and Perl (and even zsh), which substitute the entire array when you do $array, bash only substitutes the first element. To get the entire array you need the slightly clumsy ${array[*]}. The # gives you the length of the variable. Since bash arrays count from zero (zsh on the other hand counts form 1), the last element is one less. The surrounding $(( .. )) performs arithmetic substition.

Once you start doing more scripting, you will probably want to read up on some scripting articles. The standard guide seems to be the Advanced Bash Scripting guide. Don't worry about the "Advanced", it starts off with the basics (apparently, I haven't read it myself). (That link is for the online version, if you google around you can find a tarball of the article that you can read offline.)

Alternatively (should have thought of this yesterday), you could do something like

first element:

Code:
first=$(ls -v prefix*.tga | nead -n1)
last element (-r == reverse order):

Code:
last=$(ls -rv prefix*.tga| head -n1)
or

Code:
last=$(ls -v prefix*.tga | tail -n1)

Last edited by dawkcid; 06-09-2007 at 11:06 AM.
 
Old 06-09-2007, 01:40 PM   #6
babag
Member
 
Registered: Aug 2003
Posts: 419

Original Poster
Rep: Reputation: 31
thanks again dawkcid. tried this:

$ last=$(ls -rv *.bmp| head -n1)

as a simple variant on a directory that had a lot of
bitmaps in it. wanted to test to see what it did and
got this error:

bash: /bin/ls: Argument list too long

any thoughts? the directory in question has almost
30000 bitmap files in it. this may be typical of the
size of directory i'll be dealing with.

thanks for all the help,
BabaG

Last edited by babag; 06-09-2007 at 01:42 PM.
 
Old 06-09-2007, 02:47 PM   #7
dawkcid
Member
 
Registered: May 2007
Location: UK
Distribution: LFS,Slackware,Slamd64,NetBSD
Posts: 102

Rep: Reputation: 15
Bugger, I shoud've expected that with the number of files you mentioned.

I was going to suggest

find ... | sort -n

but I just realised that won't work becuse sort's numeric sort only compares numbers (not numerical parts of strings, like ls -v).

How about just listing every file, and grepping out the ones you want, e.g.

Code:
last=$(ls -rv | grep '\.bmp$' | head -n1)
This will avoid problems with command line length.

Last edited by dawkcid; 06-10-2007 at 12:54 PM.
 
Old 06-09-2007, 04:14 PM   #8
babag
Member
 
Registered: Aug 2003
Posts: 419

Original Poster
Rep: Reputation: 31
thanks again dawkcid. the above cmd just paused for a
few seconds then came back to the cmd line. no results.
i'm a perma noob at this stuff so i'm probably missing
something obvious. should i be doing something with grep
to get a result to display?

sorry for the stupidity,
BabaG
 
Old 06-09-2007, 11:04 PM   #9
babag
Member
 
Registered: Aug 2003
Posts: 419

Original Poster
Rep: Reputation: 31
dawkcid, this worked:


find . -name "something-to-identify-with*" | sort -n | head -n 1

and this for the last file:

find . -name "something-to-identify-with*" | sort -nr | head -n 1


one question: the directory i tested contains files in the naming
format:

Budgies_12345.bmp


the return from my cmd line is :

./Budgies_12345.bmp


what's with the ./? is there some simple syntaxing i
can use to get rid of it in the returned value?

thanks a lot. your tips got me to it.

BabaG

Last edited by babag; 06-09-2007 at 11:14 PM.
 
Old 06-10-2007, 01:01 PM   #10
dawkcid
Member
 
Registered: May 2007
Location: UK
Distribution: LFS,Slackware,Slamd64,NetBSD
Posts: 102

Rep: Reputation: 15
The ./ is part of the pathname generated by find (meaning the current directory). You can get rid of it with basename or using bash's parameter expansion syntax (which will be more efficient than spawning basename):

Code:
filename=$(basename $filename)
or

Code:
filename=${filename##*/}
You could work basename into the find pipeline, such as

filename=$(basename $(find ... | sort ... | head ...))

Using other way you'd need to do it afterwards since bash cannot do nested parameter expansion. Thus,

filename=$(find ....)
filename=${filename##*/}

Either of those should get rid of the ./
 
Old 06-10-2007, 01:25 PM   #11
babag
Member
 
Registered: Aug 2003
Posts: 419

Original Poster
Rep: Reputation: 31
perfect! thanks for all the help. this works great now.

francois diquad
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
bash shell script read file line by line. Darren[UoW] Programming 57 04-17-2016 06:07 PM
BASH: read every line in the files and use the line as parameters as another program tam3c36 Programming 10 12-07-2010 01:42 PM
bash+awk to fix MP3 tags Yalla-One Programming 7 11-12-2005 09:11 AM
powershell on slackware? slinky2004 Slackware 2 10-07-2005 04:42 AM
Finally Found A Fix For AUDIGY LS Line Out! KohlyKohl Linux - Hardware 0 08-29-2004 05:41 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:37 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration