views:

143

answers:

5

The following works fine on Mac OS X:

#!/bin/bash
R CMD Sweave myfile.Rnw
pdflatex myfile.tex
open myfile.pdf

Now, I realize that these 3 lines of code are really helpful for my work – independently of some particular file. Thus I'd like to use the file as an argument. I know how to use an argument itself but have problems splitting the input after the string and concat it afterwards. If I was able to split the filename argument like:

split($1,".") # return some array or list ("name","ext")

Or is there a simpler, completely different way than using Python within a shell script?

Thx in advance for any general advice and examples as well !

+6  A: 

I do all my shell scripting in python.
It's easier to read, more powerful and works on windows as well.

Martin Beckett
same, glad to see i'm not the only one.
wheaties
I with Martin. For anything non-trivial I like to use Python.
Dr. Watson
Do you use ipython, python yourfile.py or call it from within a shell script?
ran2
I don't use python as an interactive shell - I just write all those little scripts in it, eg. "python doit.py". Used to use awk but it's a pain to quote one liners in windows
Martin Beckett
+6  A: 

You could just take the base name as an argument and use $1.Rnw, $1.tex, and $1.pdf. Python is great for shell scripts, but I usually stick with bash for things less than 10 lines long.

If you really want to take a file name, you can use cut -f 1 -d '.' $1.

Nathon
+1 Yeah, no need for overkill
Matt Williamson
+1 this is really smart. Love it because, this works without any additional code I did not know before :) . Besides "Python is great for shell scripts, but I usually stick with bash for things less than 10 lines long" was just my intuition – am glad I was not too much off the mark.
ran2
kudos, the longer I think about it, I gotta accept this great answer. Thx for every else for sharing your thoughts.
ran2
A: 

Python is certainly a good choice for shell scripting, however for a simple example as yours using bash is easier. Yet again, for compiling LaTeX I'd recommend a makefile and using GNU make. In case you haven't heard of it, you can do sth like this:

FILE = your_tex_filename
INCLUDES = preface.tex introduction.tex framework.tex abbreviations.tex 

all: $(FILE).pdf

$(FILE).pdf: $(FILE).tex $(INCLUDES) $(FILE).aux index bibliography
    pdflatex $(FILE).tex

index: $(FILE).tex
    makeindex $(FILE).idx

bibliography: $(FILE).bib $(FILE).aux
    bibtex $(FILE)

$(FILE).aux: $(FILE).tex
    pdflatex $(FILE).tex

# bbl and blg contain the bibliography
# idx and ind contain the index
.PHONY : clean
clean:
    rm *.aux *.bak $(FILE).bbl $(FILE).blg \
       *.flc *.idx *.ind *.log *.lof *.lot *.toc core \
       *.backup *.ilg *.out *~

and then simply compile your source document w/

make

or clean up after building w/

make clean

A downside is that you'd need a dedicated makefile for each of your projects, but w/ a template that is not much of an issue. hth

PS: A great introduction to string manipulation w/ the bash shell can be found at http://www.faqs.org/docs/abs/HTML/string-manipulation.html.

Gerald Senarclens de Grancy
Thx, did not know of this, so learned something new :) . Though it does not apply to my problem, because I use Sweave / R to create my .tex file.
ran2
Ok, I overread/ misunderstood that part. Hope the 'basename' approach and the other tips will help you!
Gerald Senarclens de Grancy
+2  A: 

The Python one liner would be:

python -c "print '$1'.split('.')[0]"

But Nathon's idea "Use the base name as the argument." is IMHO the best solution.

Edit:

You use "backticks" to use text that a program put on the standard output, like so:

eike@lixie:~> FOO="test.foo"
eike@lixie:~> BAR=`python -c "print '$FOO'.split('.')[0]"`
eike@lixie:~> echo $BAR

This should result in:

test
Eike
+1 the use of -c option is great
pygabriel
How can I use the result in a shell variable? Eh got it myself:foo=$(python -c "print '$1'.split('.')[0]")
ran2
Backticks: ``Command here`` I'll put it into my answer.
Eike
+1  A: 

I agree with Gerald's suggestion to use Makefiles, but his downside comment (dedicated makefile for each project) isn't quite correct, as Makefiles can be made more generic.

Replace $(FILE) with $@ and then invoke with "make foo".

I'd leave this as a comment to Gerald's answer but do not have the points to do so.

mankoff
Thanks for the comment - it's a good suggestion. Actually - I'm too lazy to do 'make foo' (well... not really - it's more of a habit). When initializing a new project, the makefile can be initialized automatically as well :)
Gerald Senarclens de Grancy