Uigetfile - Is there a neater way of moving my files?

Hello Community,
After my script has run I want to do a little housekeeping and save various .mat, .jpg and .fig files to a specific file (that I create with user input slightly earlier in the script). At the moment I create the new folder with this:
mkdir(input('Enter new folder name (same as img count): ', 's'))
then when its time to save the .mat, .jpg and .fig to this newly created folder I use this code:
[filename, pathname, filterindex] = uigetfile( ...
{ '*.mat','MAT-files (*.mat)'; ...
'*.fig;*.fig','figures (*.fig)'; ...
'*.jpg;*.jpg','Jpgs (*.jpg)'}, ...
'Pick a file', ...
'MultiSelect', 'on');
to manually select the relevant .mat, .jpg and .fig files from the dialogue box and basically drag and drop them in the newly created folder and then close the dialogue.
This doesn't seem like a very efficient way of doing this - but I haven't managed to work out another way.
Does anyone have any suggestions on how to improve this workflow?
Regards,
10B.

 Accepted Answer

In your script, set a desired destination folder and use fullfile to save them directly so that there is no need to move them.
desiredFolder = 'c:\whatever';
baseFileName = 'myApp.mat';
fullFileName = fullfile(desiredFolder, baseFileName);
Then do whatever you already to to save or create these files. If you don't use a folder, then they just save to the current directory and you have to move them like you're doing (but don't want to do).

15 Comments

Hello again Image Analyst,
Thanks for your response. There is a slight problem with hardcoding the destination folder as it changes each time I run the script.
What I am doing is (coincidentally) analysing a series of images with the script, and this outputs several variables that I want to save in a new folder that is named after the original image.
So, if the original image is for example, IMG_3465.jpg, I would want to save all the new output in a folder named '3465' so I can go back to it later.
Is there a way to use your approach, but with user input so the folder name and destination can be changed each time?
Regards
10B.
Why ask the user for information you already know? Since your code already know the image name (otherwise it can't be processing it!), why ask him again for part of it? Just extract the relevant part and use that in your code to create the folder without any user interaction.
inputimage = 'IMG_3465.jpg'; %obtained any way you want
%... processing code
%...
newfolder = regexp(inputimage, '(?=IMG_)\d+', 'match', 'once');
newfullpath = fullfile(pwd, newfolder);
mkdir(newfullpath);
%... use folder
This is an ideal solution Guillaume - exactly the sort of thing I wanted to do - but just didn't have the knowledge so thanks for sharing.
I have tried to add this code in (only changing inputimage to myImage), but I get the following error:
Undefined function 'regexp' for input arguments of type 'uint8'.
Error in ScriptCorrection1 (line 137)
newfolder = regexp(myImage, '(?=IMG_)\d+', 'match', 'once');
Error in run (line 63)
evalin('caller', [script ';']);
suggesting that 'regexp' is a problem - but I have a full Matlab suite so I am uncertain as to why this is.
Any further thoughts on this?
inputimage is supposed to be the filename of the image. You're passing the content of the image to regexp whereas it expects a string.
Yes, OK - in that example I did try to pass the image itself. However, this is how I read in the image:
fullFileName = fullfile(folder, baseFileName);
myImage = imread(fullFileName);
as each time an image is selected from a dialogue box. The variable 'fullFileName' contains a string as:
C:\Users\10B\Docs\MatlabFiles\Images\IMG_2524.JPG
and 'baseFileName' contains just the image name:
IMG_2524.JPG
I have also tried using these variables written in your suggested code replacing 'inputimage', both with and without 'single quotes', and... yep still no joy.
I do get the following warning though:
Warning: Directory already exists.
> In ScriptCorrection1 at 132
In run at 63
but line 132 refers to:
mkdir(newfullpath);
of your code. Despite its first use at Line 131 of your code, there is nowhere else in my code that 'newfullpath' is used - so I don't understand why this would be a problem.
Sorry to ask again, and I really appreciate the help - but what is the step that am I missing here?
First, learn to use the debugger. Put a breakpoint on line 132 and when it's hit, see what the value of newfullpath is.
The warning is telling you that the directory you're trying to create already exists. I suspect that's because newfullpath is not what you think it is. Note that in my example,
newfullpath = fullfile(pwd, newfolder);
newfullpath is a subdirectory of the current directory (returned by pwd). It may be your Matlab user directory or some other directory if you've changed the current directory with cd. I've actually no idea where you want to create your new directory. Replace pwd with whatever is appropriate.
Similarly, I use a particular regular expression (any group of digits following IMG_) to extract the name of the folder. Again, you may want something different.
Thanks - I'm going to have a go at debugging to see if that helps me understand the problem. I will let you know how it turns out.
Regarding the other elements, ie creating newfullpath as a subdirectory of the current directory - is actually correct ie this is what I want to happen. Using cd to check the directory returns that this is the correct location ie the parent directory that I want to put the child (sub) into. So in that case using pwd is correct as well.
I have double checked the regular expression use and this also seems correct for my purposes - so no problem there.
I just appear to be going round and round with creating a new directory that apparently already exists - but I certainly can't see it and it doesn't appear on searches!
Anyhow, now to debug and try to work out the problem...
Thanks again.
Finally - I've cracked it!
There was a syntax error in your suggestion Guillaume - the following line simply needs square brackets instead of parenthesis:
newfolder = regexpi(inputimage, '(?=IMG_)\d+', 'match', 'once');
So, becoming:
newfolder = regexpi(inputimage, '[?=IMG_]\d+', 'match', 'once');
I also changed 'regexp' to 'regexpi' so that font case size is not an issue. The only minor query is that the folder name is prefixed with an underscore so, "_1234", but I will try to play around with the syntax to get this right.
Thanks again Guillaume - I got there in the end!
Footnote: Guillaume - add a new answer to this question (not just a comment as here) so I can give you an accepted answer for all your help.
Sorted the underscore issue now too. Adding a power to the syntax precludes anything that is within the squared brackets, so does exactly what I want and only picks up the numeric values:
newfolder = regexpi(baseFileName, '[^?=IMG_]\d+', 'match', 'once');
By "simply" changing the parentheses for square brackets you have completely changed the meaning of Guillaume's regular expression. The original regular expression should have checked if that particular sequence of characters precedes one or more digits, except Guillaume made a small mistake, a missing '<':
>> regexp('IMG_1234','(?=IMG_)\d+','match','once')
ans =
>> regexp('IMG_1234','(?<=IMG_)\d+','match','once')
ans = 1234
What you have now simply checks that one single character before one or more digits is not any of the ones in the brackets. This is basically a useless check, because that first character will be one of the digits themselves... so for your filenames it is practically equivalent to this:
>> regexp('IMG_1234','\d+','match','once')
ans = 1234
Learning how regular expressions are defined takes a lot of reading the documentation and plenty of practice. It is not just a "simple" replacement of parentheses with square brackets, because this actually changes the entire meaning of the regular expression.
This can help you define regular expressions, and see their effects:
Thanks for adding more insight into this Stephen - I will have a play with your suggested syntax to see how it affects everything, but in fact, what I wanted to do was to parse down the folder name to be just the numeric values that are contained within the original filename, so loading an image called 'IMG_1234.JPG' and it ending up in a folder called '1234' is actually what I achieved with the syntax changes that I made. It may be a rough way to do it - but it worked! (I have to take the small wins when they come...)
I will take a look at using your suggested
regexp('IMG_1234','(?<=IMG_)\d+','match','once')
particularly if this is a more correct way to achieve the same outcome.
Thanks for the link to your helper. I hadn't come across this previously, but will investigate further.
Regards,
10B.
Yes, as Stephen has pointed out, my regular expression was simply missing a '<' (not sure how that came about, since I did test it with the '<' in place). Your regular expression with [] does not do what you want. It means:
[^....] match a single character that is not any of the character in the enclosed brackets
[^?=IMG_]... so match any character that is not ?, =, I, M, G or _
...\d+ followed by one or more digit.
The regular expression returns the whole match, that is the character matched by the [..] and the digits matched by \d+. So your expression will happily match A1234, 12, 1234, IMG_1234, but not IMG_1
In the case of IMG_1234, your regular expression go over I, rejects it because of the first rule, same for M, G and _. It then go over 1 and accepts it because it's not one of ?=IMG_. It then matches 234 with \d+. It can't match IMG_1 because after the 1 has matched the [...] there is no digit left to match the \d+. As you can see your regular expression only work by accident.
My (corrected) regular expression means:
(?<=...)... look behind whatever you match for the expression in the bracket, so
(?<=IMG_')... the match has to be preceded by IMG_
...\d+ the match is a sequence of one or more digit.
This will only match 'IMG_' followed by one or more digits, and nothing else.
Right - I understand the differences a lot more now. A really useful and clear explanation to help me understand further. I genuinely didn't realise that I was sending such an incorrect command that just happened to work the way intended - but only in error! It looks like I opened another can of worms, but actually it turned out to be a really useful exercise. Thanks all for the input.
My suggestion is to scrap the regexp, you will sooner or later want to use the functionality on images that doesn't follow the current pattern (IMG_NNN.ext) and then it will break. Instead use the fileparts function - it will separate [the path-string and] the name and the extension regardless of what pattern it follows. Be lazy when possible.
Thanks Bjorn - I will have a look at the fileparts function. I was unaware of this previously.

Sign in to comment.

More Answers (0)

Categories

Asked:

10B
on 28 Sep 2015

Commented:

10B
on 5 Oct 2015

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!