Executing nested loops+foreach+csh - loops

It's been a while since I used csh formatting and I am having a little bit of trouble with a few things. Things seem so much easier to execute in Matlab, however I need to do this on the terminal because of the programs I am trying to interact with.
So here's what I want to do: I have a file del.txt that is structured like this
1
2
3
4
etc. So each value is in it's own row and there's one column for all the data. I have a bunch of other files that are within my directory. I want to match up say value 1 (which in this case is 1) with file 1 and value 2 with file 2, etc and so on and so forth. So here's what I did...
Code:
!/bin/csh
foreach a (cat del.txt)
foreach sta(ls *.HHZ)
echo a is $a
echo $sta
cat <<END>>macro.m
r $a
r $sta
END
sac macro.m
rm macro.m
end
end
However what I achieve is that it loops through all of the values in del.txt and each file and then moves on to the next file within my directory and loops through all of the values. I'm having trouble figuring out the format that this should be in to match up the correct values. I'm not doing much within the script yet until I can get them to match up. Please help Can someone tell me what I'm doing wrong? I read that the foreach command will execute all the commands on each file..but haven't been able to find a way to get around this. What I want it to do is take value 1 from del.txt and match it up with file 1 (sta) from the directory finish the loop, then take value 2 from del.txt and match it up with file 2 from the directory (sta). I've never done more than just simple iterations with csh on one subset of files, and I am not sure how to reference the values to one another. Any help would be greatly appreciated. I haven't found a simple way to do this without writing everything out. I looked at the 'for' and 'while' commands..if there is a simple way to do it I'm not seeing it.
Cheers,
K

IF I am understanding correctly, You have a txt file will list of strings and you want it to match with the files.
I am assuming by this particular statement of yours:
I want to match up say value 1 (which in this case is 1) with file 1
You mean to match the string at 1 with file name of file 1.
Here's a possible solution based on this assumption(this will help you anyway with loop):
#Store value in file.txt in a array
set file_var = `cat file.txt`
#Store file list in my_dir in a var
set my_dir = <your dir path>
set file_list_var = `ls $my_dir`
#Let's print "file Match: for every match
foreach var1 ($file_var)
foreach var2 ($file_list_var)
if("$var1" == "$var2") echo $var1 = $var2 : Match Found.
endif
endif

Related

Run TreSpEx analysis

I am trying to run TreSpex analysis on a series of trees, which are saved in newick format as .fasta.txt files in a folder.
I have a list of Taxa names saved in a .txt file
I enter:
perl TreSpEx.v1.pl -fun e -ipt *fasta.txt -tf Taxa_List.txt
But it won't run. I tried writing a loop for each file within the folder but am not very good with them and my line of
for i in treefile/; do perl TreSpEx.v1.1.pl -fun e -ipt *.fasta.txt -tf Taxa_List.txt; done
won't work because -ipt apparently needs a name that starts with a letter or number
In your second example you are actually doing the same thing as in first (but posible several times).
I'm not familiar with TreSpEx or know Bash very well for that matter (which it seems you are using), but you might try something like below.
for i in treefile/*.fasta.txt ; do
perl TreSpEx.v1.1.pl -fun e -ipt $i -tf Taxa_List.txt;
done
Basically, you need to use a variable from the for loop (i) to pass name of each file to the command.

Can't fill bash array

I'm running Ubuntu 14.04 and am trying to fill an array in a shell script so that I can loop over it and utilize its contents to fill a text file. However, there's a snag: it doesn't seem to be filling.
I've simplified the larger script that I'm working with down to the essential issue, reprinted below:
WL_START=1
WL_END=5
WL_INC=1
wl_range=$(seq $WL_START $WL_INC $WL_END)
declare -a WL
for i in $wl_range # loop through sequence and fill array
do
WL[$i]=${wl_range[$i]}
done
echo $wl_range
echo ${wl_range[1]}
echo $WL
echo ${WL[1]}
However, my output looks like this:
1 2 3 4 5
empty line
empty line
empty line
Any ideas? I know that people say to just use seq to fill the array, but I had the same problem there as well.
Too much work.
WL=($(seq $WL_START $WL_INC $WL_END))
wl_range is a string consisting of space-delimited numbers, not an array. Your for loop should simply look like
for i in $wl_range; do
WL[i]=$i
done
That said, don't use the for loop; use #IgnacioVazquez-Abrams' answer.

Can i format output of matlab command such that i can use it to declare a new variable?

It's best explained with an easier example. Say some script in MATLAB gives me a cell array of strings:
temp = dir;
names = {temp.name}'
ans =
'folder1'
'folder2'
'file1'
I would like to use this output in another script, in another matlab session. Ideally, in the second script i would write
names = {'folder1', 'folder2', 'file1'}
but this means copypasting the output right under "ans = " and then manually adding the commas and curly brackets. In my case the cell array is quite large so this is undesirable. Even more it feels clumsy and there could be an easier way. Is there any way to make matlab print the output in such a way that i do not have to do this?
Exactly the same thing would be nice to know for matrices instead of cell arrays!!
I am aware of saving the variable in a .mat file and loading it, but i was wondering if the above is also possible (it would be cleaner in my case).
Personally I would advise the use of a cleaner way of handling this (such as mat files).
But then again sometimes the time spent setting these up is just not worth it for simple tasks which are unlikely to be repeated much...
For matrices there is a builtin function to do this, for cells however we would need produce a sting with the required format...
Matrix
For 1d or 2d matrices mat2str provides this functionality
mat2str(eye(2))
ans =
[1 0;0 1]
Cell
However to my knowledge there is no such builtin function for cells.
For a 1d cell array of strings the following will give the output in a copyable format:
['{',sprintf('''%s'' ',names{:}),'}']
ans =
{'folder1' 'folder2' 'file1' }
note: the stings in the cells cannot contain the ' character
If i understand you correctly, you are getting the names output from one script and want to use it within another script. Since you then cannot pass it as function argument, you are currently copying it over. One could do that with eval and copy&paste around:
names = {'folder1'
'folder2'
'file1'};
% create the command
n = length(names);
cmd = sprintf(['names = {',repmat('''%s'', ', 1, n-1) ,'''%s''}'], names{:}); % '%s, %s, ...., %s' format
% cmd contains the string: names_new = {'folder1', 'folder2', 'file1'}
% eval the cmd in script 2
eval(cmd) % evals the command names = {'folder1', 'folder2', 'file1'}
But this is generally very bad practice as it gets insanely hard to debug if something goes wrong somewhere. Also it makes you copy and paste things around, which i feel is uncomfortable. How about storing them in a txt file and loading them in the second script? It gets things done autmatically.
names = {'folder1'
'folder2'
'file1'};
% write output to file
fid = fopen('mynames.txt', 'w'); % open file to write something
fprintf(fid, [repmat('%s, ',1, n-1), '%s'], names{:});
fclose(fid);
% here comes script 2
fid = fopen('mynames.txt', 'r'); % open file to read something
names_loaded = textscan(fid, '%s');
names_loaded = names_loaded{:};
fclose(fid)
I think the key here is that you have a variable in 1 place, and want to use it in a different case.
In that situation you don't want to copy the output matlab generates, you just want to save the value itself.
After finding the result just do this:
save names
Later you can load this variable with
load names
Check doc save and doc names for more extensive examples. You may for example want to save all relevant variables in a file with a more generic name.

How to run same code on multiple files, or all files in directory

so I am very new to coding and recently wrote a little program that involved R and sox. It looked like this
file <- "test.mp3"
testSox = paste("sox ",file," -n spectrogram -o ",file,".png stats",sep='')
sox = system(testSox, intern = TRUE)
print(sox)
Now, instead of assigning the one file manually within the code, I would just like to have this code read through all the mp3s in a folder automatically. Is this possible? Any help would be greatly appreciated. Thanks!
EDIT: Actually, I should add that I tried list.files, but when it comes to running the system() command, I get
"Error in system(command, as.integer(flag), f, stdout, stderr) :
character string expected as first argument"
Here's the list.files code I tried:
> temp = list.files(path = ".", pattern=".mp3")
>
> file <- temp
>
> firstSox = paste("sox ",file," -n spectrogram -o ",file,".png stats",sep='')
> sox = system(firstSox, intern = TRUE)
Error in system(command, as.integer(flag), f, stdout, stderr) :
character string expected as first argument
> print(sox)
I'm guessing this is not the correct route to go? Because I basically need to replace 'file' in the firstSox line with each mp3 that's in the temp array. So instead of running:
file <- "test.mp3"
...I would just like to have it re-assign each time for every file in the folder..., so it runs through as test.mp3, then 1.mp3, then 2.mp3, then 3.mp, etc.
I've scoured the net, and just feel like I've hit a brick wall. As stated in the comments, I've read up on loops, but for some reason I can't wrap my head around how to incorporate it into what I have written. I feel like I just need someone to show me at least the way, or maybe even write me an example so I can wrap my head around it. Would greatly appreciate help and any tips on what I'm doing wrong and could correct. Thanks.
Try the below code. I am using dir() instead of list.files, just because I find it easier. Remember there are many ways to do the same thing in R.
files <- dir(path = ".",pattern = ".mp3") #Get all the mp3 files
for(f in files) { #Loop over the mp3 files one at a time
firstSox = paste("sox ",f," -n spectrogram -o ",f,".png stats",sep='')
sox = system(firstSox, intern = TRUE)
print(sox)
}
Your firstSox variable will be a vector of commands to run (paste will generate a vector, one string for each element of file). So now you just need to run each command through system
One way to do this and capture the output is to use the lapply or sapply function:
sox <- lapply( firstSox, function(x) system(x, intern=TRUE) )
In this code lapply will run the function for each element of firstSox one at a time, the function just takes the current element (in x) and passes that to system. Then lapply gathers all the outputs together and combines them into a list that it puts into sox.
If the results of each run give the same shape of results (single number or vector of same length) then you can use sapply instead and it will simplify the return into a vector or matrix.

trying to use while read loop to save result to an array

Quick question, can i do this?:
while IFS=: read menu script
do
echo "$x. $menu"
command[x]="$script"
let x++
done < file.txt
read two strings per line from a file, print one and save the other to an array..
file.txt looks like this:
File Operations:~/scripts/project/File_Operations.sh
Directory Operations:~/scripts/project/Directory_Operations.sh
Process Management:~/scripts/project/Process_Management.sh
Search Operations:~/scripts/project/Search_Operations.sh
Looks right. 2 things.
You need to initialise x. x=0
When you use x as a subscript it needs the $. i.e. command[$x]="$script"
And done forget the {}s when referencing the command array. e.g. ${command[0]}
What shell are you using? Works for me in bash, I just prepended the following two lines to the script:
#!/bin/bash
x=0
Without setting $x to 0, the user is presented with
. File Operations
1. Directory Operations
2. Process Management
3. Search Operations

Resources