Shell script over some files - shell

I have to do some things in some files from a directory in solaris. In that directory, I have thousands of files. Some of them, begin with FAC_. I need to make an array variable with those names of files (which four first letters name are FAC_), and then go over the array to do some task to each file.
How can I accomplish that?
Thanks

I think the simplest approach would be something like this:
files="FAC_*"
for file in $files; do
echo "$file"
done
If the files aren't in the same directory as the script you can use the following line to retrieve them.
files="$path/FAC_*"

Related

How to create tar files automatically

I like to create tar-files to distribute some scripts using bash.
For every script certain configuration-files and libraries (or toolboxes) are needed,
e.g. a script called CheckTool.py needs Checks.ini, CheckToolbox.py and CommontToolbox.py to run, which are stored in specific folders on my harddisk and need to be copied in the same manner on the users harddisk.
I can create a tarfile manually for each script, but i like to have it more simple.
For this i have the idea to define a list of all needed files and their pathes for a specific script and read this in a bashscript, which creates the tar file.
I started with:
#!/bin/bash
while read line
do
echo "$line"
done < $1
Which is reading the files and pathes. In my example the lines are:
./CheckTools/CheckMesh.bs
./Configs/CheckMesh.ini
./Toolboxes/CommonToolbox.bs
./Toolboxes/CheckToolbox.bs
My question is how do I have to organize the data to make a tar file with the specified files using bash?
Or is there someone having a better idea?
No need for a complicated script, use option -T of tar. Every file listed in there will be added to the tar file:
-T, --files-from FILE
get names to extract or create from FILE
So your script becomes:
#!/bin/bash
tar -cvpf something.tar -T listoffiles.txt
listoffiles.txt format is super easy, one file per line. You might want to put full path to ensure you get the right files:
./CheckTools/CheckMesh.bs
./Configs/CheckMesh.ini
./Toolboxes/CommonToolbox.bs
./Toolboxes/CheckToolbox.bs
You can add tar commands to the script as needed, or you could loop on the list files, from that point on, your imagination is the limit!

OS X bash For loop only processes one file in a directory

I'm trying to get this code to process all files in a directory : https://github.com/kieranjol/ifi-ffv1/blob/master/ifi-ffv1.sh
I run it in the terminal and add path to file ./ifi-ffv1.sh /path/to/file.mov. How can I get it to move on to the next? I'll also need to make sure that it only processes AV files, such as .avi/.mkv/*.mov etc.
I've tried using while loops with shift but I can't get that to work either.
I've tried adding a specific path like here but I'm failing http://www.cyberciti.biz/faq/unix-loop-through-files-in-a-directory/
I've tried this https://askubuntu.com/a/315338 and it keeps looping the same file rather than moving on to the next one. http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html this didn't help me either.
I know this is going to be a horribly simple solution but I'm very new to this.
You don't actually have any kind of loop in your code. You need to do something like
for file in path/to/*.avi path/to/*.avg
do
./ifi-ffv1.sh "$file"
done
which will loop through all the specified files and substitute each one for $1
You can put whatever file names you want instead of the path/to/*.avi path/to/*.avg. If you cd to the directory first, you can leave out the paths, and just use *.avi *.avg
To do it all in one script, do something like this:
cd <your directory>
for file in *.avi *.avg
do
<your existing script here>
done
replacing all the $1's in your script with "$file" (not duplicating any quotes you already have, of course)

Can the shell direct where a program places its output files?

Can the shell override where output files are placed? (Not the console/screen output, but files created by a program.) I have a script that currently runs a sequence of input files through a program and for each one produces a lot of different output files.
for i in `seq 1 24`
do
../Bin/myprog inputfile.$i.in
done
Is there a way to create new directories for each run of the program and place the corresponding output files in each directory? So I would get dir1: <output files from run 1>; dir2 <output files from run 2> etc. I suppose one way would be to just write another script to create directories and sort all the files after the program(s) had run, but is there a more elegant way to do it?
As suggested in the comments, this might be what you need, assuming that your program just dumps output into the current working directory.
for i in `seq 1 24`
do
mkdir $i
pushd $i
../../Bin/myprog ../inputfile.$i.in
popd
done
If you are trying to change where an existing program (e.g., myprog) writes its files, this is only possible if the program writes its files relative to the current directory. In this case, the outer script that invokes myprog, can create a "destination" directory and chdir to it before invoking myprog.
If the myprog program writes to an absolute path, e.g., /var/tmp/myprog.tmp, the only way to override where this write actually goes is to place a symbolic link at the absolute path linking to the desired destination. This will only work if the program (myprog) doesn't first delete an existing file before writing to it.
The third and most extreme possibility for directing absolute file path writes is to create a chroot'ed file system, in which the myprog output files will be contained, after which the outer script can copy or move them to where they are desired.
To summarize: other than changing the source, setting the working directory for relative-path output files, or chrooting a filesystem for absolute-path files, there really is no "elegant" way to replace the actual output files used in a program.

Rename output of Shell script(s)

I am trying to create a script that runs an another script and changes the name from the output.
Here is the script so far:
#! /bin/bash
i=1
for N in mediainput.iso mediainput2.iso
do
x264transcode $N
mv $N $((i++))
done
This don`t that well. It just moves the files and renames them.
I need to first run the x264transcode and then rename the output of that. Since they all get the same name when x264transcode as processed the files.
Its okey that the name the files are changed to are 1 then 2 and so on.
But it would be a plus if there where a method of getting the name of the folder the file was inside or the file itself. Maybe choosing between them for different scenarios.
Example below:
~/Videos/Summer Vacation 2009/dvd.iso
Output from x264: VIDEO01.mkv
Output from rename script: Summer-Vacation-2009.mkv
Does x264transcode always call its output VIDEO01.mkv? Are all the video files dvd.iso? If so, something like this, to also get the correct filename with hyphens:
cd ~/Videos
for I in */dvd.iso
do
x264transcode $I
mv VIDEO01.mkv `dirname $I|tr ' ' -`.mkv
end
This is assuming x264transcode stores VIDEO01.mkv in the current directory rather than the directory its input file is located in.

Using the result of a command as an argument in bash?

To create a playlist for all of the music in a folder, I am using the following command in bash:
ls > list.txt
I would like to use the result of the pwd command for the name of the playlist.
Something like:
ls > ${pwd}.txt
That doesn't work though - can anyone tell me what syntax I need to use to do something like this?
Edit: As mentioned in the comments pwd will end up giving an absolute path, so my playlist will end up being named .txt in some directory - d'oh! So I'll have to trim the path. Thanks for spotting that - I would probably have spent ages wondering where my files went!
The best way to do this is with "$(command substitution)" (thanks, Landon):
ls > "$(pwd).txt"
You will sometimes also see people use the older backtick notation, but this has several drawbacks in terms of nesting and escaping:
ls > "`pwd`.txt"
Note that the unprocessed substitution of pwd is an absolute path, so the above command creates a file with the same name in the same directory as the working directory, but with a .txt extension. Thomas Kammeyer pointed out that the basename command strips the leading directory, so this would create a text file in the current directory with the name of that directory:
ls > "$(basename "$(pwd)").txt"
Also thanks to erichui for bringing up the problem of spaces in the path.
This is equivalent to the backtick solution:
ls > $(pwd).txt
To do literally what you said, you could try:
ls > `pwd`.txt
which will use the full pathname, which should be fine.
Note that if you do this in your home directory, which might
be in /home/hoboben, you will be trying the create /home/hoboben.txt,
a text file in the directory above.
Is this what you wanted?
If you wanted the directory to contain a file named after it, you would get
the basename of the current directory and append that with .txt to the pwd.
Now, rather than use the pwd command... why not use the PWD environment variable?
For example:
ls > $PWD.txt
or
ls > ${PWD}.txt
is probably what you were trying to remember with your second example.
If you're in /home/hoboben and you want to create /home/hoboben/hoboben.txt, try:
ls > ${PWD}/${PWD##*/}.txt
If you do this, the file will contain its own name, so most often, you would remedy this in one of a few ways. You could redirect to somewhere else and move the file or name the file beginning with a dot to hide it from the ls command as long as you don't use the -a flag (and then optionally rename the resulting file).
I write my own scripts to manage a directory hierarchy of music files and I use subdirectories named ".info", for example, to contain track data in some spare files (basically, I "hide" metadata this way). It works out okay because my needs are simple and my collection small.
I suspect the problem may be that there are spaces in one of the directory names. For example, if your working directory is "/home/user/music/artist name". Bash will be confused thinking that you are trying to redirect to /home/user/music/artist and name.txt. You can fix this with double quotes
ls > "$(pwd).txt"
Also, you may not want to redirect to $(pwd).txt. In the example above, you would be redirecting the output to the file "/home/user/music/artist name.txt"
The syntax is:
ls > `pwd`.txt
That is the '`' character up underneath the '~', not the regular single quote.
Using the above method will create the files one level above your current directory. If you want the play lists to all go to one directory you'd need to do something like:
#!/bin/sh
MYVAR=`pwd | sed "s|/|_|g"`
ls > /playlistdir/$MYVAR-list.txt
to strip all but the directory name
ls >/playlistdir/${PWD##/*}.txt
this is probably not what you want because then you don't know where the files are (unless you change the ls command)
to replace "/" with "_"
ls >/playlistdir/${PWD//\//_}.txt
but then the playlist would look ugly and maybe not even fit in the selection window
So this will give you both a short readable name and usable paths inside the file
ext=.mp3 #leave blank for all files
for FILE in "$PWD/*$ext"; do echo "$FILE";done >/playlistdir/${PWD##/*}.txt

Resources