Automatic renaming of files - operating-system

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'"

Related

Stata: Unable to return Global Macro of Filename

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.

Faster copyfiles Matlab

I have a folder origin_training with subfolders like FM, folder1, folder2, ... . I can get the list of image files in .png format into a cell called FM.
FM_dir = fullfile(origin_training, 'FM');
FM = struct2cell(dir(fullfile(FM_dir, '*.png')))';
My goal is to match the names in my folder with the images in my cd, and make a new folder FM with the images from cd. Image names in the two paths are identical. I can do that with:
% mother_folder = '...' my current directory
filenames = FM(:,1);
destination = fullfile(mother_folder, 'FM', FM(:,1));
cellfun(#copyfile,filenames, destination);
This is really slow. Takes minutes even for small amounts of images (~30).
My current directory has ~ 10000 images (the ones that correspond to FM, folder2, folder3, ...). What am I missing here?
An alternative would be to create a shell command and execute it. Assuming FM contains full paths for each file, or relative paths from the current directory, then:
FM_dir = fullfile(origin_training, 'FM');
destination = fullfile(mother_folder, 'FM');
curdir = cd(FM_dir);
FM = dir('*.png');
cmd = ['cp ', sprintf('%s ',FM.name), destination];
system(cmd);
cd(curdir);
If you're on Windows, replace 'cp' by 'copy'.
Note that here we're not creating a shell command per file to be copied (presumably what copyfile does), but a single shell command that copies all files at once. We're also not specifying the name for each copied file, we specify the names of the files to be copied and where to copy them to.
Note also that for this to work, mother_folder must be an absolute path.
I somehow put my code into a function and now it works at expected speed. I suspected that cd had to do with the low speed so I am only passing the full directories as character vectors.
The same approach works for my purpose or with a slight modification to just copy from A to B. As now, it works to match files in A to those on B and copy to B/folder_name
function [out] = my_copyfiles(origin_dir, folder_name, dest_dir, extension)
new_dir = fullfile(origin_dir, folder_name);
% Get a cell with filenames in the origin_dir/folder_name
% Mind transposing to have them in the rows
NEW = struct2cell(dir(fullfile(new_dir, extension)))';
dest_folder = fullfile(dest_dir, folder_name);
% disp(dest_folder)
if ~exist(dest_folder, 'dir')
mkdir(dest_folder)
end
%% CAUTION, This is the step
% Use names from NEW to generate fullnames in dest_dir that would match
filenames = fullfile(dest_dir, NEW(:,1));
destination = fullfile(dest_folder, NEW(:,1));
% if you wanted from origin, instead run
% filenames = fullfile(new_dir, NEW(:,1));
% make the copies
cellfun(#copyfile,filenames, destination);
%Save the call
out.originDir = new_dir;
out.copyFrom = dest_dir;
out.to = dest_folder;
out.filenames = filenames;
out.destination = destination;
end

Movefile when string is a variable

This is within a forloop aimed at moving multiple files within multiple folders into the 'RawData' directory. I am having issues with using movefile. I would like the file being moved to be a varaible and not a string typed into the command.
Here is a portion of the folder list if needed to better understand:
'Data-20141003T091843-1-Eyes Open on Flat Surface-Force.csv'
'Data-20141003T091843-1-Eyes Open on Flat Surface-Results.csv'
'Data-20141003T091923-2-Eyes Closed on Flat Surface-Force.csv'
'Data-20141003T091923-2-Eyes Closed on Flat Surface-Info.csv'
'Data-20141003T091923-2-Eyes Closed on Flat Surface-Results.csv'
'Data-20141003T092208-3-Limits of Stability-Force.csv'
'Data-20141003T092208-3-Limits of Stability-Info.csv'
>>foldername = foldername.name;
directoryname = 'C:\Users\murphy\Documents\MATLAB\RawData\';
folderdirectory = strcat(directoryname,foldername);
cd(folderdirectory);
folderdir = dir('*.csv');
folderList = {folderdir.name}'; %List of Files in folder
for f = 1:length(folderList) **movefile(folderList(f),'C:\Users\murphy\Documents\MATLAB\RawData')**
end
folderList is a cellstr.
In your for loop you need to pass folderList{f} instead of folderList(f).
for f = 1:length(folderList)
movefile(folderList{f},'C:\Users\murphy\Documents\MATLAB\RawData')
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.

loop within loop - detecting end of loop in autohotkey

Let's say I have a bunch of filenames with the names of fruits in them. I want to auto-rename them based upon a folder full of reference files (dummy txt files which contain the names of fruits, a period, then the name of a dessert).
apple.tart, grape.jelly, kiwi.cake, mango.icecream, banana.pudding, cherry.cobbler, etc
I want to select all the files to be renamed, and drag them onto my script.
If a file in the loop already contains a certain combo, such as "cherry.cobbler", I simply want the dummyfile to be discarded, and the file should NOT be renamed "cherry.cobbler.cobbler"
If a file in the loop contains the word "kiwi", I want it to be changed so that it contains "kiwi.cake".
If a file in the loop contains a fruit not listed, I want a catchall string to be added. So "kumquat" would become "kumquat.nodessert"
It is condition #3 which is causing me trouble. I can't seem to come up with the right syntax to specify when the last dummyfile has been checked.
here's some pseudo code
Loop %0%
{
Path := %A_Index%
Loop %Path%, 1
LongPath = %A_LoopFileLongPath%
SplitPath LongPath, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
Loop thru folder of fruit combos
{
Stringsplit filenames from fruit-combos folder into %fruit% and %dessert%
If OutNameNoExt contains %fruit%.%dessert%
{
FileDelete fruit.combo dummyfile
continue; skip to next file to rename
)
If OutNameNoExt contains %fruit%
{
FileDelete fruit.combo dummyfile
StringReplace %fruit% with %fruit%.%dessert%
continue; skip to next file to rename
)
If OutNameNoExt not contains fruit.combo AND all dummy files have been checked
{
StringReplace %fruit% with %fruit%.nodessert
)
}
; proceed with next selected file
}
put condition 3 outside the inner loop and it seems to work