How to ask the user how many file extensions to search for

I currently have a script which find files in a folder with a matching string that the user inputs.
I also have code where the user enters the file extensions he wants the script to look for.
ext1 = inputdlg('Please enter file extension #1: **\*. ');
ext2 = inputdlg('Please enter file extension #2: **\*. ');
ext3 = inputdlg('Please enter file extension #3: **\*. ');
fileData = [dir(fullfile(fileLoc,char(ext1))); dir(fullfile(fileLoc,char(ext2))); dir(fullfile(fileLoc,char(ext3)))];
What I want to do instead of ask the user how many different file extensions he wants to look for and then ask for them accordingly.
(e.g. User inputs he wants to search for 5 different file extensions and the script asks for 5)
I'd like to do this instead of just hard-coding in how many file extensions he can search for.

 Réponse acceptée

Adam Danz
Adam Danz le 13 Sep 2019
Modifié(e) : Adam Danz le 13 Sep 2019
That's too much work (for you and the user). Instead, the user could just list all file extensions in the first dialog, separated by commas. Then you can separate that list into individual extensions.
  • extList is a cell array of character vectors that contain the user's input list
  • nExt is the number of extensions entered
ext = inputdlg('Please enter file extensions separated by a comma: **\*. Example: txt, csv, ogg');
if ~isempty(ext) %check if user entered anything
% Separate selections
extList = strtrim(strsplit(ext{1},','));
extList(cellfun(@isempty,extList)) = []; % get rid of empties (if any)
nExt = numel(extList); %number of extensions
end
For example, in the inputdlg enter this: txt, csv, ogg, xlsx
If there is a set list of possible file extensions, a better idea would be to use a listbox where the user can merely select from a set of options.

12 commentaires

Great response!
I will definitely do it this way.
However, how would I implement this into the dir function?
fileData = dir(fullfile(fileLoc,char(extlist)));
This gives me an error, hence why I was using
fileData = [dir(fullfile(fileLoc,char(ext1))); dir(fullfile(fileLoc,char(ext2))); dir(fullfile(fileLoc,char(ext3)))];
for the three seperate file extensions.
The easiest way is to loop doing a dir() for each extension and concatenating the results.
Adam Danz
Adam Danz le 13 Sep 2019
Modifié(e) : Adam Danz le 13 Sep 2019
fileData = [];
for i = 1:nExt
fileData = [fileData, dir(fullfile(fileLoc,extList{i}))];
. . .
end
*Not tested
Nom
Nom le 13 Sep 2019
Modifié(e) : Nom le 13 Sep 2019
Wow thanks so much,
Only small issue I'm having is concatenating the results.
for i = 1:nExt
fileData = dir(fullfile(fileLoc,extList{i}));
strcat(fileData,fileData)
end
I'm not sure how to add the chars onto themselves.
The result of dir() is not characters.
Adam made a small mistake:
for i = 1:nExt
fileData = [fileData; dir(fullfile(fileLoc,extList{i}))];
. . .
end
Notice the change from comma to semi-colon. dir() returns a column vector of struct.
dir() returns a structure array. What chars are you concatenating?
I updated my comment above with a method of concatenating strcture arrays but it is not tested.
Nom
Nom le 13 Sep 2019
Modifié(e) : Nom le 13 Sep 2019
I inputted ".docx, pdf, txt"
as an example with the following code which Walter edited
for i = 1:nExt
fileData = [fileData; dir(fullfile(fileLoc,extList{i}))];
end
However, this gives an "Undefined function or variable 'fileData'."
If it's worth mentioning, I do have the above code outside of the if statement
That's why you have to include the line below prior to the loop.
fileData = [];
I can't thank you enough,
It works perfectly I love it!
If there's one thing (totally optional), currently the extensions require the user to input " **\*. " before every entry otherwise it will not search the entire file name.
How might I input this into the code so the user doesn't have to?
Again, I really appreciate your help.
fileData = [];
for i = 1:nExt
fileData = [fileData; dir(fullfile(fileLoc, ['**\*.', extList{i}]))];
end
Note: if you are using **\ then that says to search all subdirectories. In order to know which directory the file was found in, you will need to look at the folder field of the information returned by dir. You can generate the entire list of fully-qualified names by using
fullfile( {fileData.folder}, {fileData.name})
Thank you! Yes I've already implemented it in that exact way,
weirdly enough running this script from a .m file works flawlessly
But when I moved the new code into my app designer's code it gives this error.
Cell contents reference from a non-cell array object.
on this line
extList = strtrim(strsplit(ext{1},','));
Which is pretty confusing because this is the exact code which worked straight from a .m script file.
The app designer's code was functioning with my old way (three file extensions hard coded in)
So I'm not sure why app designer is seeing something differently
Adam Danz
Adam Danz le 13 Sep 2019
Modifié(e) : Adam Danz le 13 Sep 2019
Hmmm, could you show us exactly what's in ext and the result of class(ext)?
[update]
I just embedded the code from my answer into app designer and entered a variety of inputs including several extensions, 1 extension, and empty, and there was no error.

Connectez-vous pour commenter.

Plus de réponses (2)

Right before
extList = strtrim(strsplit(ext{1},','));
is executed.
K>> ext
ext =
'txt, pdf, docx'
K>> class(ext)
ans =
'char'
Above what I put into the command script

2 commentaires

So somehow ext is a character vector instead of a cell array of char.
As a general fix: after you have called
ext = inputdlg('Please enter file extensions separated by a comma:. Example: txt, csv, ogg: ');
add
ext = cellstr(ext);
Though you might have to check isempty() first.
inputdlg should always return a cell array:
Where is the 'txt, pdf, docx' char array coming from? I can't be the output to inputdlg.

Connectez-vous pour commenter.

Nom
Nom le 13 Sep 2019
Awesome!
I'm forever in your debt
Works perfectly!

17 commentaires

I know I've already asked so much, but I was wondering if there was a way I could have hyperlinks outputted in an excel file.
Currently I have this set up running to output into excel, is there anyway to just make them into hyperlinks by default so I could just click on the file path and have it open directly up?
outputData = [{'Starting Path:' fileLoc ' ';
'Time to Execute:' [sprintf('%.2f',overallTime+overallTime2) 's'] ' ';
'File Count:' num2str(sum(~finalFlag)) ' ';
'Date' 'Size' 'File'};
fileDates(~finalFlag) num2cell(fileSizes(~finalFlag) ./1024) fullPaths(~finalFlag)];
xlswrite(outputFile,outputData);
Do you want to write a hyperlink to an excel file or do you want to write a hyperlink to the command window that, when selected, opens the excel file?
Straight into an excel file.
So that opening the excel file the file path would be hyper linked so you could just click on it to take you directly to it.
awesome, thank you once again.
Nom
Nom le 16 Sep 2019
Modifié(e) : Nom le 16 Sep 2019
So what's happening now weirdly is if I enter docx and search for the terms "test1 test2 test3" it works. But if I enter more than just docx e.g. (docx, txt) or even just txt alone. It gives the following error:
Error using horzcat
Dimensions of matrices being concatenated are not consistent.
Error in Testapp/StartButtonPushed (line 109)
stmFileSearch(app,fileLoc,outputFile,rejectFile)
The error occurs on the line below, I've also marked it in the full code I've pasted below.
fileDates(~finalFlag) num2cell(fileSizes(~finalFlag) ./1024) fullPaths(~finalFlag)];
The code I'm using is below:
tic;
if ~isempty(ext) %check if user entered anything
% Separate selections
ext = cellstr(ext);
extList = strtrim(strsplit(ext{1},','));
extList(cellfun(@isempty,extList)) = []; % get rid of empties (if any)
nExt = numel(extList); %number of extensions
end
fileData = [];
for i = 1:nExt
fileData = [fileData; dir(fullfile(fileLoc, ['**\*.', extList{i}]))];
end
% Get the dates & Sizes
fileDates = {fileData.date}';
fileSizes = [fileData.bytes]';
% Get the full paths
fullPaths = fullfile( {fileData.folder}, {fileData.name});
overallTime = toc;
strinput = char(fil);
tic;
xorString2 = strsplit(strinput);
ignoreFlag2 = ~contains(fullPaths,xorString2,'IgnoreCase',true);
finalFlag = ignoreFlag2;
overallTime2 = toc;
% Create the output
outputData = [{'Starting Path:' fileLoc ' ';
'Time to Execute:' [sprintf('%.2f',overallTime+overallTime2) 's'] ' ';
'File Count:' num2str(sum(~finalFlag)) ' ';
'Date' 'Size' 'File'};
%vvvvvvvvvvvvvvvvvvvv ERROR vvvvvvvvvvvvvvvvvvvvvvvv
fileDates(~finalFlag) num2cell(fileSizes(~finalFlag) ./1024)]; fullPaths(~finalFlag)];
%^^^^^^^^^^^^^^^^^^^^ ERROR ^^^^^^^^^^^^^^^^^^^^^^^
xlswrite(outputFile,outputData);
Unfortunately I could not run all of your code because I don't have the value for "fil". I can suggestion some areas to look at.
xlswrite(outputFile,outputData);
As you can read here, the 2nd input to xlswrite() is a "two-dimensional numeric, character array, or string array, or, if each cell contains a single element, a cell array". It doesn't look like that is the case in your code.
fileDates(~finalFlag) num2cell(fileSizes(~finalFlag) ./1024)
I'm not sure what's happening here (above). it looks like you're horizontally concatenating two things that are different sizes.
I can't easily troubleshoot if I can't reproduce the problem so if you still need some help, makes sure we have code and data so that we can step through each line of your code.
Nom
Nom le 16 Sep 2019
Modifié(e) : Nom le 16 Sep 2019
I apologize,
fil is what the user puts to "filter" the file names with a given string in this case the fil should be test1 test2 test3, so that program will search for files which have matching strings in the folder "fileLoc"
What I found weirdly is that the program works if I remove the header of the file path printed
fullPaths = strrep(fullPaths,fileLoc,'')'; % Remove the header path
I have no clue why this makes it work, but I need the file headers to show up so I may hyper link them
Scratch that, it doesn't work, I encounter the same problem :(
I just can't understand why inputting docx, is the only extension which works. Everything else even on its own e.g.(txt) gives that error
Ok, since this section below is what's causing the problem, could you run the code up to that point and then save all of the needed variables to a mat file, and then attach that file.
outputData = [{'Starting Path:' fileLoc ' ';
'Time to Execute:' [sprintf('%.2f',overallTime+overallTime2) 's'] ' ';
'File Count:' num2str(sum(~finalFlag)) ' ';
'Date' 'Size' 'File'};
%vvvvvvvvvvvvvvvvvvvv ERROR vvvvvvvvvvvvvvvvvvvvvvvv
fileDates(~finalFlag) num2cell(fileSizes(~finalFlag) ./1024)]; fullPaths(~finalFlag)];
%^^^^^^^^^^^^^^^^^^^^ ERROR ^^^^^^^^^^^^^^^^^^^^^^^
So I need
  • fileLoc
  • overallTime
  • overallTime2
  • fileFlag
That way I can run that section.
Sure thing,
I've attached the file below.
I really appreciate your help again
Nom
Nom le 16 Sep 2019
Modifié(e) : Nom le 16 Sep 2019
Ok so this code below works but I have one major issue
% Get the files
tic;
if ~isempty(ext) %check if user entered anything
% Separate selections
ext = cellstr(ext);
extList = strtrim(strsplit(ext{1},','));
extList(cellfun(@isempty,extList)) = []; % get rid of empties (if any)
nExt = numel(extList); %number of extensions
end
fileData = [];
for i = 1:nExt
fileData = [fileData; dir(fullfile(fileLoc, ['**\*.', extList{i}]))];
end
% Get the dates & Sizes
fileDates = {fileData.date}';
fileSizes = [fileData.bytes]';
% Get the full paths
fullPaths = fullfile( {fileData.folder}, {fileData.name});
%NEW LINE ADDED BELOW
fullPaths = strrep(fullPaths,fileLoc,'')'; % Remove the header path
%NEW LINE ADDED ABOVE
% h1 = ['=HYPERLINK('];
% h2 = fileLoc;
% h3 = ')';
% strcomb = strcat(h1,h2,h3);
% fullPaths = strrep(fullPaths,fileLoc,strcomb);
overallTime = toc;
strinput = char(fil);
tic;
xorString2 = strsplit(strinput);
ignoreFlag2 = ~contains(fullPaths,xorString2,'IgnoreCase',true);
finalFlag = ignoreFlag2;
overallTime2 = toc;
% Create the output
outputData = [{'Starting Path:' fileLoc ' ';
'Time to Execute:' [sprintf('%.2f',overallTime+overallTime2) 's'] ' ';
'File Count:' num2str(sum(~finalFlag)) ' ';
'Date' 'Size (kb)' 'File'};
fileDates(~finalFlag) num2cell(fileSizes(~finalFlag) ./1024) fullPaths(~finalFlag)];
xlswrite(outputFile,outputData);
% Create the rejected output
outputData = [{'Starting Path:' fileLoc ' ';
'Time to Execute:' [sprintf('%.2f',overallTime+overallTime2) 's'] ' ';
'File Count:' num2str(sum(finalFlag)) ' ';
'Date' 'Size (kb)' 'File'};
fileDates(finalFlag) num2cell(fileSizes(finalFlag) ./1024) fullPaths(finalFlag)];
xlswrite(rejectFile,outputData);
msgbox('Operation Completed');
I have this line in there which removes the file path's header e.g. ("C:\Users\User1\Desktop\Search Script\1.xlsx" becomes just 1.xlsx.
fullPaths = strrep(fullPaths,fileLoc,'')';
anyway to avoid this, I just want to be able to add hyper links in the future, and for that i require the full file path
Why not just comment that line out?
It's so weird, it gives the
Error using horzcat
Dimensions of matrices being concatenated are not consistent.
Error in Testapp/StartButtonPushed (line 109)
stmFileSearch(app,fileLoc,outputFile,rejectFile)
if I comment it out
Okay guys, I solved the problem by just adding
fullPaths = strcat(fileLoc,fullPaths);
right before
outputData = [{'Starting Path:' fileLoc ' ';
'Time to Execute:' [sprintf('%.2f',overallTime+overallTime2) 's'] ' ';
'File Count:' num2str(sum(~finalFlag)) ' ';
'Date' 'Size (kb)' 'File'};
fileDates(~finalFlag) num2cell(fileSizes(~finalFlag) ./1024) fullPaths(~finalFlag)];
I'm terribly sorry for wasting everyone's time,
I've spent four hours trying to fix this myself.
I'm not sure how that solved the error you were getting.
Notice at the end of this line you transpose the array.
fullPaths = strrep(fullPaths,fileLoc,'')'; % Remove the header path
% HERE ^
So when you comment that out, fullPaths remains as a row-cell-array.
That causes the error when you try to horizontally concatenate the bottom line below.
outputData = [{'Starting Path:' fileLoc ' ';
'Time to Execute:' [sprintf('%.2f',overallTime+overallTime2) 's'] ' ';
'File Count:' num2str(sum(finalFlag)) ' ';
'Date' 'Size (kb)' 'File'};
fileDates(finalFlag) num2cell(fileSizes(finalFlag) ./1024) fullPaths(finalFlag)];
%|___column array___| {______________Column array_________| |____Row array______|
Oh wow, I completely forgot about that.
Thank you so much

Connectez-vous pour commenter.

Catégories

En savoir plus sur Share and Distribute Software dans Centre d'aide et File Exchange

Produits

Version

R2017b

Community Treasure Hunt

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

Start Hunting!

Translated by