How to get the path part of a filename? - matlab

I want to get the path part of a file name in MATLAB like dirname and basename in Linux. I've tried to turn to find a function like strrchr, but I failed. I know strtok, strfind and textscan can be used, but I want to accomplish this with not more than two statements.

For this particular problem I suggest you use the fileparts function:
[path, filename, extension] = fileparts(str)

Nick's answer definitely does what you ask for, but here's an alternative answer using regexprep:
regexprep(str, '(.+)(?:\\|/)(.*)', '$1')
If you'd want to capture the filename (extension included), use the $2 token instead of $1.
It's a good exercise for regular expressions, which prove to be very useful in MATLAB when parsing text.

Related

use a variable with whitespace Perl

I am currently working on a project but I have one big problem. I have some picture with a whitespace in the name and I want to do a montage. The problem is that I can't rename my picture and my code is like that :
$pic1 = qq(picture one.png);
$pic2 = qq(picture two.png);
my $cmd = "C:\...\montage.exe $pic1 $pic2 output.png";
system($cmd);
but because of the whitespace montage.exe doesn't work. How can I execute my code without renaming all my pictures?
Thanks a lot for your answer!
You can properly quote the filenames within the string you pass to system, as #Borodin shows in his answer. Something like: system("montage.exe '$pic1' '$pic2'")
However, A more reliable and safer solution is to pass the arguments to montage.exe as extra parameters in the system call:
system('montage.exe', $pic2, $pic2, 'output.png')
Now you don't have to worry about nesting the correct quotes, or worry about files with unexpected characters. Not only is this simpler code, but it avoids malicious injection issues, should those file names ever come from a tainted source. Someone could enter | rm *, but your system call will not remove all your files for you.
Further, in real life, you probably are not going to have a separate scalar variable for each file name. You'll have them in an array. This makes your system call even easier:
system('montage.exe', #filenames, 'output.png')
Not only is that super easy, but it avoids the pitfall of having a command line too long. If your filenames have nice long paths (maybe 50-100 characters), a Windows command line will exceed the max command length after around 100 files. Passing the arguments through system() instead of in one big string avoids that limitation.
Alternatively, you can pass the arguments to montage.exe as a list (instead of concatenating them all into a string):
use strict;
use warnings;
my $pic1 = qq(picture one.png);
my $pic2 = qq(picture two.png);
my #cmd = ("C:\...\montage.exe", $pic1, $pic2, "output.png");
system(#cmd);
You need to put quotes around the file names that have spaces. You also need to escape the backslashes
my $cmd = qq{C:\\...\\montage.exe "$pic1" "$pic2" output.png};
In unix systems, the best approach is the multi-argument form of system because 1) it avoids invoking a shell, and 2) that's the format accepted by the OS call. Neither of those are true in Windows. The OS call to spawn a program expects a command line, and system's attempt to form this command line is sometimes incorrect. The safest approach is to use Win32::ShellQuote.
use Win32::ShellQuote qw( quote_system );
system quote_system("C:\\...\\montage.exe", $pic1, $pic2, "output.png");

How to Use fullfile in Matlab?

I am studying Suever's answer where I do not understand its application with fullfile in Code 1.
Code 1
filename=strcat('/Users/masi/Images/', 'p.1');
save(fullfile(filename,'.mat'),'time');
saveas(her, fullfile(filename,'.png'));
Output
Error using save
Cannot create '.mat' because '/Users/masi/Images/p.1' does not
exist.
Code 2
filename=strcat('/Users/masi/Images/', 'p.1');
save(strcat(filename,'.mat'),'time');
saveas(her, strcat(filename,'.png'));
Success!
Change made based on Daniel's answer
filenameMat=fullfile('/Users/masi/Images/', 'p.1', '.mat');
save(filenameMat,'time');
but still getting
Error using save
Cannot create '.mat' because '/Users/masi/Images/p.1.mat' does not
exist.
I do not understand.
Why is code 1 giving the error?
You are using fullfile for a wrong application. The documentation clearly explains the parameters:
Folder and file names, specified as strings and cell arrays of strings.
You input a filename without extension and a file extension, hat is not what fullfile is made for. It will insert a file separator between both:
>> fullfile('foo','.bar')
ans =
foo\.bar
fullfile would be the right function to construct filename.

Warning Control Character '\S' is not valid when concatinating two strings

I have two variables such as:
path='data\voc11\SegmentationClassExt\%s.png'
name='123'
I want to concatenate two strings into one like so:
data\voc11\SegmentationClassExt\123.png
I used the code below:
sprintf(path, name)
However I receive the following error:
Warning: Control Character '\S' is not valid. See 'doc sprintf' for control characters valid in the format string.
ans =
dataoc11
I am using MATLAB on Windows. Could you give me any solution for that. I tried to change path='data\\voc11\\SegmentationClassExt\\%s.png' and when I did that, the above code will work. However, the current data is
path='data\voc11\SegmentationClassExt\%s.png';
use the matlab function fullfile
filename = fullfile ( path, [name '.png'] );
or
filename = fullfile ( path, sprintf ( '%s.png', name ) );
Note: you should avoid using path as a variable as it is already a Matlab function
Before we start, it's highly advised that you do not use path as a local variable. path is a global variable that MATLAB uses to resolve function scope, especially if you are going to use any functions from toolboxes. Overwriting path with your own string will actually make MATLAB not function properly. Use a different variable name.
Now to resolve your problem, you can use either fullfile as what #matlabgui has suggested, or if you don't care about OS compatibility and are only working in Windows, you can either manually change the path as you have placed so that you can introduce two back slashes and it will indeed work on Windows OS, or you can perhaps use a string replace function so that all back slashes will be accompanied with an additional back slash.
Either one of these two methods will work:
Method 1 - Using regular expressions
pat = 'data\voc11\SegmentationClassExt\%s.png';
pat_new = regexprep(pat, '\\', '\\\\');
The function regexprep performs a string replacement by regular expressions. We search for all single backslashes and replace them with double backslashes. Note that the single back slash \ is a special character in regular expressions so if you explicitly what to look for back slashes, you must place an additional back slash beside it.
Method 2 - Using strrep
pat = 'data\voc11\SegmentationClassExt\%s.png';
pat_new = strrep(pat, '\', '\\');
strrep stands for String Replace. It works very similar to regular expressions as we have discussed above. However, what's nice is that you don't have to append an additional back slash when looking for the actual character.
Once you do this, you can use sprintf as normal:
pat_new = sprintf(pat_new, name);

use fprinft with an unknown format in matlab

I would like to save the output of several evals ( don't know the input of those ) in a file. Now I don't know the tpye of those evals They could be arrays or strings or integer or anything, so I can not really write fprinft(fileID, '%s\n', eval(somethingsomething)); since I don't know what the second parameter should be. Is there a way a for me to save those in a file?
You can save the results of the eval in a local variable and check the resulting type with class(v) and use printf accordingly.
I believe you can just save result of eval with fwrite(), why would you use fprintf?

Substitute only one part of a string using perl

I have an array that have some symbols that I want to remove and even thought I find a solution, I will like to know if this is the right way because I'm afraid if I use it with array will remove the character that I might need on future arrays.
Here is an example item on my array:
$string1='22 | logging monitor informational';
so I try the following:
$string1=~ s/\s{6}\|(?=\s{6})//;
So my output is:
22 logging monitor informational
Is the other way that best match "|". I just want to remove the pipe character.
Thanks in advance
"I want to remove just the pipe character."
OK, then do this:
$string1 =~ s/\|//;
This will remove the first pipe character in the string. (You said in another comment that you don't want to remove any additional pipe characters.) If that's not what you want, then I'd suggest telling us exactly what you do want. We can't read minds, you know.
In the mean time, I'd also strongly recommend reading the Perl regular expressions tutorial.