I write code where I load a lot of project data. I want to keep my pathnames in the code relative to some location of this project on the disk, i.e. not having it configured or hard-coded.
Is there function in matlab to do some like this?
In python I would write:
ROOT = os.path.dirname(__file__)
The best way to do this is to combine fileparts with mfilename('fullpath'). (All examples assume the executing m-file containing these statements lives in /home/suever/code/stackoverflow.m)
mfiledir = fileparts(mfilename('fullpath'));
/home/suever/code
Then you can use fullfile to construct any paths you need from that. Now if you have a file (data.mat) stored in the same directory:
filename = fullfile(mfiledir, 'data.mat');
/home/suever/code/data.mat
Of if the file is actually in the parent directory.
filename = fullfile(mfiledir, '..', 'data.mat');
/home/suever/data.mat
If you want just the parent directory that an m-file is in, you can apply fileparts twice and only keep the second output.
[~, reldir] = fileparts(fileparts(mfilename('fullpath')));
code
I would recommend the use of full paths in the first examples as those are completely independent of the user's current working directory.
A better recipe to organize your code is to have a function like this:
function [ path ] = get_path()
path = [regexprep(mfilename('fullpath'), ['\' filesep '[\w\.]*$'],'') filesep];
end
You drop it inside +foo/get_path.m file and than call something like foo.get_path() that returns the path to +foo folder.
Related
I keep running across this error in my code:
Path = 'C:\Users\18606\OneDrive\Documents\Spheroids For Brandon\Spheroids\1-8WT';
Content = dir(Path);
SubFold = Content([Content.isdir]); % Keep only the directories
MyData = [];
for k = 3:length(SubFold)
F = fullfile(Path, SubFold(k).name);
fileID = fopen(F);
MyData{end+1} = fopen(fileID,'%s\n');
fclose(fileID);
Resulting in the error:
Error using fopen
Invalid filename (line 8)
The code is trying to iterate over multiple images in multiple subfolders of the main. The goal is to process the images with an edge detection algorithm for each file, but that's besides the point. Why would the program give an invalid file name when the path, content and subfolders are all specified in the code? Do the variables mentioned have anything to do with the error? Finally, is there a better way to open and read the images iteratively?
Reading in files sequentially is indeed usually done through looping over a dir() call, i.e. your strategy is valid. What's going wrong here, is that Path is a path to a directory, not a file. SubFold then are only directories as they are found on the Path. fullfile(Path, SubFold(k).name) finally creates a path to a subdirectory of Path. A subdirectory is not a file, thus fopen will tell you that it's an incorrect filename.
You'll probably need another dir() call, e.g. dir(F) to get all files on the path specified by F.
I have a matlab script that wants to load a .mat file that is in a directory fixed relative to the location of the script. The script itself could be in different places relative to the current working directory, so the location of the .mat file is not known relative to it. How do I specify the location of the file to load relative to the script that is executing?
The function mfilename returns the name of the currently running script. This however does not return the full path to the script. You probably want this and so you can specify the 'fullpath' option to return the full path to the actual script itself, including the name of the script.
You just want the actual directory of where the file is, and so first use mfilename to get the full path to the actual file, then use fileparts to actually extract the actual directory of where the file is. fileparts returns the directory of where the file is, the file name itself and the extension. You just want the first output argument and don't care about the other outputs. Once you have this, you can then use the actual directory then append this string with the location of your .mat file:
p = mfilename('fullpath');
[pathstr,~,~] = fileparts(p);
d = fullfile(pathstr, 'path', 'to', 'your', 'file.mat');
fullfile builds a directory string that is OS independent, so for each subdirectory you want to indicate to get to your .mat file, place these as separate input strings up until you reach the file you want. d will contain the full path of your .mat file relative to the currently running script, which you can then use to load accordingly.
I'd like to remove '-2' from the filenames looking like this:
EID-NFBSS-2FE454B7-2_TD.eeg
EID-NFBSS-2FE454B7-2_TD.vhdr
EID-NFBSS-2FE454B7-2_TD.vmrk
EID-NFBSS-3B3BF9FA-2_BU.eeg
EID-NFBSS-2FE454B7-2_PO.txt
So as you may see the names of the files are different and there are different kind of extensions as well. All what I want to do is remove '-2' from all of the filenames. I was trying use this:
pattern = '-2';
replacement = '';
regexprep(filename,pattern,replacement)
and I got the results in the console, but after many attempts I have no idea how to 'say' to MATLAB switch the filnames in the same location.
#excaza hit it right on the money. You'll have to probe your desired directory for a list of files via dir, then loop through each filename and remove any occurrences of -2, then use movefile to rename the file, and delete to delete the old file.
Something like this comes to mind:
%// Get all files in this directory
d = fullfile('path', 'to', 'folder', 'here');
directory = dir(d);
%// For each file in this directory...
for ii = 1 : numel(directory)
%// Get the relative filename
name = directory(ii).name;
%// Replace any instances of -2 with nothing
name_after = regexprep(name, '-2', '');
%// If the string has changed after this...
if ~strcmpi(name, name_after)
%// Get the absolute path to both the original file and
%// the new file name
fullname = fullfile(directory, name);
fullname_after = fullfile(directory, name_after);
%// Create the new file
movefile(fullname, fullname_after);
%// Delete the old file
delete(fullname);
end
end
The logic behind this is quite simple. First, the string d determines the directory where you want to search for files. fullfile is used to construct your path by parts. The reason why this is important is because this allows the code to be platform agnostic. The delineation to separate between directories is different between operating systems. For example, in Windows the character is \ while on Mac OS and Linux, it's /. I don't know which platform you're running so fullfile is going to be useful here. Simply take each part of your directory and put them in as separate strings into fullfile.
Now, use dir to find all files in this directory of your choice. Replace the /path/to/folder/here with your desired path. Next, we iterate over all of the files. For each file, we get the relative filename. dir contains information about each file, and the field you want that is most important is the name attribute. However, this attribute is relative, which means that only the filename itself, without the full path to where this file is stored is given. After, we use regexprep as you have already done to replace any instances of -2 with nothing.
The next point is important. After we try and change the filename, if the file isn't the same, we need to create a new file by simply copying the old file to a new file of the changed name and we delete the old file. The function fullfile here helps establish absolute paths to where your file is located in the off-chance that are you running this script in a directory that doesn't include the files you're looking for.
We use fullfile to find the absolute paths to both the old and new file, use movefile to create the new file and delete to delete the old file.
My current directory is under C, for example, "C:\xxx\"
Now, I want to export my processed wav files to a subfolder in my current directory, for example, "\wav_results\".
What I have done is declaring a filepath variable:
wav_dir = '\wav_results\';
wavwrite(...., [wav_dir wav_name]) %wav_name is the name of the wav file
The error says no such file or directory. I do not want to use the full directory path for wav_dir because I need to move this script from place to place. Anyone has good suggestion?
Thanks~
Use mkdir before you call wavwrite:
wav_dir = '\wav_results\'; %'
if not(exist('testresults','dir'))
mkdir(wav_dir);
end
wavwrite(...., [wav_dir wav_name])
I have 4 folders in the same directory where each folder contains ~19 .xls files. I have written the code below to obtain the name of each of the folders and the name of each .xls file within the folders.
path='E:\Practice';
folder = path;
dirListing = dir(folder);
dirListing=dirListing(3:end);%first 2 are just pointers
for i=1:length(dirListing);
f{i} = fullfile(path, dirListing(i,1).name);%obtain the name of each folder
files{i}=dir(fullfile(f{i},'*.xls'));%find the .xls files
for j=1:length(files{1,i});
File_Name{1,i}{j,1}=files{1,i}(j,1).name;%find the name of each .xls file
end
end
Now I'm trying to import the data from excel into matlab by using xlsread. What I'm struggling with is knowing how to load the data into matlab within a loop where the excel files are in different directories (different folders).
This leaves me with a 1x4 cell named File_Name where each cell refers to a different folder located under 'path', and within each cell is then the name of the spreadsheets wanting to be imported. The size of the cells vary as the number of spreadsheets in each folder varies.
Any ideas?
thanks in advance
I'm not sure if I'm understanding your problem, but all you have to do is concatenate the strings that contain directory (f{}) and the file name. Modifying your code:
for i=1:length(dirListing);
f{i} = fullfile(path, dirListing(i,1).name);%obtain the name of each folder
files{i}=dir(fullfile(f{i},'*.xls'));%find the .xls files
for j=1:length(files{1,i});
File_Name{1,i}{j,1}=files{1,i}(j,1).name;%find the name of each .xls file
fullpath = [f{i} '/' File_Name{1,i}{j,1}];
disp(['Reading file: ' fullpath])
x = xlsread(fullpath);
end
end
This works on *nix systems. You may have to join the filenames with a '\' on Windows. I'll find a more elegant way and update this posting.
Edit: The command filesep gives the forward or backward slash, depending on your system. The following should give you the full path:
fullpath = [f{i} filesep File_Name{1,i}{j,1}];
Take a look at this helper function, written by a member of the matlab community.
It allows you to recursively search through directories to find files that match a certain pattern. This is a super handy function to use when looking to match files.
You should be able to find all your files in a single call to this function. Then you can loop through the results of the rdir function, loading the files one at a time into whatever data structure you want.