Stata: Unable to return Global Macro of Filename - global

I am using filelist to generate a dataframe of each folder and the files contained in it. I would like to save each folder name and file name with an observation number x to be able to pull their names out later.
ssc install filelist
filelist
//Save each file's name and corresponding folder:
forvalues x = 1 / `=_N' { //for every row in the filelist dataframe shown
local file = filename[`x']
global folder_`x' dirname[`x'] //save the folder name as folder_i, i = 1, 2, ... _N
global file_`x' filename[`x'] //save the file name as file_i, i = 1, 2, ... _N
}
global filecount `=_N'
This runs smoothly, and if I was to run di $file_2, for instance, it would produce the given filename. The issue I have is that then when I try to use this and access these Globals later on, they appear to have saved the "filename[`x']" rather than the actual filename. For instance, if I run:
import excel "InterestRates.xlsx", sheet("US") firstrow
di $file_2
Then I get the error filename not found. I have tried changing up my `' and "" and {} in many different ways, and I still cannot seem to get this to reference the actual filename. Any help would be greatly appreciated!

There are two ways to assign local or global macros: with an equal sign, and without. If it is assigned without an equal sign, the content will be stored as it is. With an equal sign, the content will be evaluated first.
clear
input str8 filename
"file.dta"
end
global file_1 filename[1]
global file_2 = filename[1]
di "$file_1"
di "$file_2"
Result:
. di "$file_1"
filename[1]
. di "$file_2"
file.dta

Here is a slight alteration to Wouter's code which still gives me the error:
cd [MY_PATH_HERE]
ssc install filelist
filelist
//Save each file's name and corresponding folder:
forvalues x = 1 / `=_N' { //for every row in the filelist dataframe shown
local file = filename[`x']
global folder_`x' dirname[`x'] //save the folder name as folder_i, i = 1, 2, ... _N
global file_`x' filename[`x'] //save the file name as file_i, i = 1, 2, ... _N
}
export excel test.xlsx, firstrow(var)
import excel different.xlsx, firstrow clear
di $file_1
This then still produces the filename not found error as before. It works fine when telling Stata to import the same Excel (test.xlsx) you just saved, but if you import a different Excel, it causes issues. I don't understand why this is the case though if you are saving it as a global macro.

Related

Having trouble conditionally moving files based on their names

I am trying to write a script that will auto sort files based on the 7th and 8th digit in their name. I get the following error: "Argument must be a string scalar or character vector". Error is coming from line 16:
Argument must be a string scalar or character vector.
Error in sort_files (line 16)
movefile (filelist(i), DirOut)
Here's the code:
DirIn = 'C:\Folder\Experiment' %set incoming directory
DirOut = 'C:\Folder\Experiment\1'
eval(['filelist=dir(''' DirIn '/*.wav'')']) %get file list
for i = 1:length(filelist);
Filename = filelist(i).name
name = strsplit(Filename, '_');
newStr = extractBetween(name,7,8);
if strcmp(newStr,'01')
movefile (filelist(i), DirOut)
end
end
Also, I am trying to make the file folder conditional so that if the 10-11 digits are 02 the file goes to DirOut/02 etc.
First, try avoid using the eval function, it is pretty much dreaded as slow and hard to understand. Specially if you need to create variables. Instead do this:
filelist = dir(fullfile(DirIn,'*.wav'));
Second, the passage:
name = strsplit(Filename, '_');
Makes name a list, so you can access name{1} or possibly name{2}. Each of these are strings. But name isn't a string, it is a list. extractBetween requires a string as an input. That is why you are getting this problem. But note that you could have simply done:
newStr = name(7:8);
If name was a string, which in Matlab is a char array.
EDIT:
Since it has been now claimed that the error occurs on movefile (filelist(i), DirOut), the likely cause is because filelist(i) is a struct. Wheres a filena name (char array) should have been given at input. The solution should be replacing this line with:
movefile(fullfile(filelist(i).folder, filelist(i).name), DirOut)
Now, if you want to number the output folders too, you can do this:
movefile(fullfile(filelist(i).folder, filelist(i).name), [DirOut,filesep,name(7:8)])
This will move a file to /DirOut/01. If you wanted /DirOut/1, you could do this:
movefile(fullfile(filelist(i).folder, filelist(i).name), [DirOut,filesep,int2str(str2num(name(7:8)))])

Automatic renaming of files

I am trying to batch rename many files within the same folder on my operating system.
I have a dataset with two variables: oldname and newname.
There are more file names in the dataset then actual files that need to be renamed so I would like to build something that matches the file with the observation in the dataset, renames the matched file, and then moves it to the new location.
For example, I have a three files in a location:
filepath/to/my/files/file1.jpg
filepath/to/my/files/file2.jpg
filepath/to/my/files/file3.jpg
A dataset with string variables:
Dataset
newname oldname
a pink files/file1.jpg
b blue files/file4.jpg
c purple files/file6.jpg
d green files/file3.jpg
e red files/file2.jpg
Here is the desired output of the program:
filepath/for/matches/pink.jpg
filepath/for/matches/red.jpg
filepath/for/matches/green.jpg
Do I need to use the ! operator to achieve what i want?
EDIT:
So far, I've got a method of moving the matches but not for renaming them:
global dir "/filepath"
global old "$dir/to/my/"
global new "$dir/for/matches"
ssc install mvfiles
preserve
keep if oldname!=.
foreach i in oldname{
mvfiles, infolder($old) outfolder($new) match(substr(`i',6,9))
}
restore
Not necessarily. You can achieve what you want by simply using the copy command.
The following should work:
clear
input str1 letter str10 newname str15 oldname
"a" "pink" "files/file1"
"b" "blue" "files/file4"
"c" "purple" "files/file6"
"d" "green" "files/file3"
"e" "red" "files/file2"
end
local inpath "filepath/to/my/files/"
local outpath "different/filepath/for/matches/"
local files : dir "`inpath'" files "*.jpg"
local obs = _N
foreach fil of local files {
forvalues i = 1 / `obs' {
local oldname = oldname[`i']
if substr("`fil'", 1, strpos("`fil'", ".") - 1) == substr("`oldname'", 7, .) {
local newname = newname[`i']
copy "`inpath'`fil'" " `outpath'`newname'.jpg"
}
}
}
Just replace the local macros inpath and outpath with your desired paths.
Note that If you also want to delete the file after you copy it, then just add the following after the copy command:
erase "`inpath'`fil'"

Renaming JPG images in matlab

I am new to matlab and image analysis. I would really appreciate some insight/help into the following problem. I am trying to rename images (jpg) in a folder that have a random name into specific (new) names. I made the an excel file with two columns the first column contains the old names and the second column the new names. I found the next code on stack overflow (Rename image file name in matlab):
dirData = dir('*.jpg'); %# Get the selected file data
fileNames = {dirData.name}; %# Create a cell array of file names
for iFile = 1:numel(fileNames) %# Loop over the file names
newName = sprintf('image%05d.jpg',iFile); %# Make the new name
movefile(fileNames{iFile},newName); %# Rename the file
end
The code gives all the photos a new name based on the old one but that is not what I want, the new names I use are not linked to the old ones. I tried the following code :
g= xlsread('names.xlsx') % names.xlsx the excel file with old and new names
for i=1:nrows(g)
image=open(g(i,1));
save(g(i,2),image);
end
It doesn't work. I get the error message :using open (line 68)
NAME must contain a single string. I don't think open is the right function to use.
Thank you !
How about this:
% Get the jpeg names
dir_data = dir('*.jpg');
jpg_names = {dir_data.name};
% Rename the files according to the .xlsx file
[~,g,~] = xlsread('names.xlsx'); % Thanks to the post of Sean
old_names = g(:,1);
new_names = g(:,2);
for k = 1:numel(old_names)
% check if the file exists
ix_file = strcmpi(old_names{k}, jpg_names);
if any(ix_file)
movefile(old_names{k}, new_names{k});
end;
end;
It seems like g = xlsread(file) reads only numeric data from file (see here). The third output argument of xlsread returns raw data including strings; does the following work? (i don't have excel and can't test it)
[~, ~, g] = xlsread('names.xlsx')
for i = 1:nrows(g)
movefile(g{i,1}, g{i,2})
end

how to make gulp.dest dynamic

I am learning to use gulp.I took a eg scenario in which I tried to copy the files based on the name if it is odd move it to odd folder otherwise move it to even. But some where destination folder is messed up. here is the folder structure and code.
1
--my
----new
-----2.txt
----1.txt
----2.txt
g = gulp.src '**/*.txt', cwd: '1'
g.pipe map (file,cb)->
filename = path.basename file.path, path.extname(file.path)
if filename % 2
dest = 'odd'
else
dest = 'even'
debugger
console.log 'destination ',dest
g.pipe gulp.dest dest
cb null,file
It is copying the even file names to odd folder.It is about the destination folder being remembered(closure I think)
If you literally only have two output destinations, the simplest solution might be to use the gulp-if plugin, like so (I don't use CoffeeScript, so you'll have to convert it yourself):
var _if = require('gulp-if');
function fileIsOdd(file) {
return path.basename(file.path, path.extname(file.path)) % 2;
}
// in your task
gulp.src('**/*.txt', {cwd: '1'})
.pipe(_if(fileIsOdd, gulp.dest('odd'), gulp.dest('even')))
What this does is process the individual file with the fileIsOdd function. If the function returns a truthy value, then the first argument is processed, otherwise the second argument is processed.

Creating variables with numbers from filename

I have a folder full of xls files, named data_00001 through data_10000. Each file has a dozen or so identically named tabs full of RV's. I am interested in reading all files and tabs and creating histograms of the RV's.
Is there a way to read in the last 5 digits of the file names and attached them to each tab name (which I saved as a variable)?
I used regexp to extract the number as a string and converted it to a double, and I used a for loop to save variable X{1,k}. How can I incorporate the saved double into this variable?
Are you looking for something like this?
filenames = ['data_00001','data_10000'];
nums = regexp(filenames, '[0-9]+', 'match');
tag = 'TAG';
for i=1:size(nums,2)
eval(['A_' tag '_' sprintf("%s",nums{1,i}) ' = zeros(1)']);
end
It creates matrices (zero in this case) with variable names
A_TAG_00001 = 0
A_TAG_10000 = 0