Wildcard file search in WScript - wsh

I need to get all the files in a folder that match a certain wildcard pattern, using JScript. For example:
var fso = new ActiveXObject("Scripting.FileSystemObject");
var folderName = "C:\\TRScanFolder\\";
var folder = fso.GetFolder(folderName);
var searchPattern = "1001-*POD*.*"
// Now I need a list of all files matching the search pattern
I know I could iterate through the folder.Files collection and test the names against a regex, but I would prefer to just get Windows to do a search and get only the ones matching. This is mostly for performance, since there could be several hundred files in the folder, but only a few will be the ones I want.
Is there a function or something that I can use to do a search? Or should I stick with a loop and regex?
Edit: Here I what I got to work with a regex. Is there a way to do it without?
var regex = /^1001-.*POD.*\..*$/i;
var files = new Enumerator(folder.Files);
for (files.moveFirst(); !files.atEnd(); files.moveNext())
{
var fileAttachment = files.item();
if (regex.test(fileAttachment.Name))
{
// Do stuff
}
}

One alternative is to shell out to the command line and use the dir command.
var wsh = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var dirName = "C:\\someFolder";
var pattern = "s*";
var fileName;
var oExec = wsh.Exec('%comspec% /c dir /on /b "' + dirName + '\\' + pattern + '"');
// wait for dir command to finish
while (oExec.Status === 0) {
WScript.Sleep(100);
}
// process output
while (!oExec.StdOut.AtEndOfStream) {
fileName = oExec.StdOut.ReadLine();
if ( fso.FileExists(fso.BuildPath(dirName, fileName)) ) {
//do stuff
WScript.Echo(fileName);
}
}

Related

Google script stops working after copying and authorizing

After making a copy of my perfectly working google sheet, together with the script that comes with it; the script itself does not work anymore in the copy.
I go through the steps of authorizing it as an app but it seems to hang when i run it on the copy. It times out after 540 odd seconds. It seems to be having trouble with DriveApp.createFolder (exectution time 540 seconds). Yet i have not changed anything in the script, works fine on the original one.
Here is the script, im pretty sure everything is fine here, it just doesn't want to work as soon as you make a copy of it. I need to make copies of this sheet for each person in my team but i can't at the moment.
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var date = SpreadsheetApp.getActiveSheet().getRange(3,2).getValue();
var time = SpreadsheetApp.getActiveSheet().getRange(4,2).getValue();
var site = SpreadsheetApp.getActiveSheet().getRange(2,2).getValue();
// iterate through all sheets in the spreadsheet and rename them according to cell B2
for( var j = 0 ; j < sheets.length; j++) {
var sourceSheet = sheets[j];
// get contents of cell B2
var newSheetName = sourceSheet.getRange("B2").getValue();
// rename sheet
sourceSheet.setName(newSheetName);
}
// create a folder from the named SNOWSURVEYS with date
var folder = DriveApp.createFolder('SNOWSURVEYS' + '_' + date + '_'+ site);
// append ".csv" extension to the sheet name
fileName = SpreadsheetApp.getActiveSheet().getName() + ".csv";
// convert all available sheet data to csv format
var csvFile = convertRangeToCsvFile_(fileName);
// create a file in the Docs List with the given name and the csv data
folder.createFile(fileName, csvFile);
var folderID = folder.getId();
var folderName = folder.getName();
var ui = UiApp.createApplication().setTitle('Your files have are in your google drive in a folder called ' + folder);
var p = ui.createVerticalPanel();
ui.add(p);
p.add(ui.createAnchor('Click here to go straight to your files ',folder.getUrl()));
SpreadsheetApp.getActive().show(ui)
}
Execution transcript printscreen

How can one to dynamically parse a CSV file using C# and the Smart Format Detector in FileHelpers 3.1?

As per in this FileHelpers 3.1 example, you can automatically detect a CSV file format using the FileHelpers.Detection.SmartFormatDetector class.
But the example goes no further. How do you use this information to dynamically parse a CSV file? It must have something to do with the DelimitedFileEngine but I cannot see how.
Update:
I figured out a possible way but had to resort to using reflection (which does not feel right). Is there another/better way? Maybe using System.Dynamic? Anyway, here is the code I have so far, it ain't pretty but it works:
// follows on from smart detector example
FileHelpers.Detection.RecordFormatInfo lDetectedFormat = formats[0];
Type lDetectedClass = lDetectedFormat.ClassBuilderAsDelimited.CreateRecordClass();
List<FieldInfo> lFieldInfoList = new List<FieldInfo>(lDetectedFormat.ClassBuilderAsDelimited.FieldCount);
foreach (FileHelpers.Dynamic.DelimitedFieldBuilder lField in lDetectedFormat.ClassBuilderAsDelimited.Fields)
lFieldInfoList.Add(lDetectedClass.GetField(lField.FieldName));
FileHelperAsyncEngine lFileEngine = new FileHelperAsyncEngine(lDetectedClass);
int lRecNo = 0;
lFileEngine.BeginReadFile(cReadingsFile);
try
{
while (true)
{
object lRec = lFileEngine.ReadNext();
if (lRec == null)
break;
Trace.WriteLine("Record " + lRecNo);
lFieldInfoList.ForEach(f => Trace.WriteLine(" " + f.Name + " = " + f.GetValue(lRec)));
lRecNo++;
}
}
finally
{
lFileEngine.Close();
}
As I use the SmartFormatDetector to determine the exact format of the incoming Delimited files you can use following appoach:
private DelimitedClassBuilder GetFormat(string file)
{
var detector = new FileHelpers.Detection.SmartFormatDetector();
var format = detector.DetectFileFormat(file);
return format.First().ClassBuilderAsDelimited;
}
private List<T> ConvertFile2Objects<T>(string file, out DelimitedFileEngine engine)
{
var format = GetSeperator(file); // Get Here your FormatInfo
engine = new DelimitedFileEngine(typeof(T)); //define your DelimitdFileEngine
//set some Properties of the engine with what you need
engine.ErrorMode = ErrorMode.SaveAndContinue; //optional
engine.Options.Delimiter = format.Delimiter;
engine.Options.IgnoreFirstLines = format.IgnoreFirstLines;
engine.Options.IgnoreLastLines = format.IgnoreLastLines;
//process
var ret = engine.ReadFileAsList(file);
this.errorCount = engine.ErrorManager.ErrorCount;
var err = engine.ErrorManager.Errors;
engine.ErrorManager.SaveErrors("errors.out");
//return records do here what you need
return ret.Cast<T>().ToList();
}
This is an approach I use in a project, where I only know that I have to process Delimited files of multiple types.
Attention:
I noticed that with the files I recieved the SmartFormatDetector has a problem with tab delimiter. Maybe this should be considered.
Disclaimer: This code is not perfected but in a usable state. Modification and/or refactoring is adviced.

How can I quickly rename folders in tfs?

I have around 200 folders which I have to rename. Each folder contain multiple children but I just want to rename the parent. I know it should not have been required in the first place but not I am already in this situation. Renaming them one by one is going to take a long time and I wanted to automate this somehow. Is it possible to do so ?
Just use command line tf.exe. For just 200 renames, you can just call tf.exe 200 times "tf rename foo bar" and then check all changes in.
You can also explore powershell option (there are tfs cmdlets).
Last but not least you can write tfs script - each line is new tf.exe command, but they all share server connection so it's speedier:
script1.tfs
"
rename foo1 bar1
rename foo2 bar2
" and you call tf #script1.tfs (the # is crucial)
Please remember to create workspace that covers all your folders first and easiest is to call tf.exe from folder that is mapped in it.
Good luck!
As suggested by MicahalMa, I used a similar approach and called rename in a loop using c#. Here is my not so elegant code.
private static void RenameDirectories()
{
string path = #"E:\Local\Development\"; //Path for parent directory
List<string> directoriesToRename = new List<string>();
string[] directories = Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly);
string tfsTool = #"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\TF.exe";
string command = "rename";
var p = new Process();
int i = 0;
foreach (string s in directories)
{
i++;
string param = command + " " + path + "\\" + s + " " + path + "\\" + s.Remove(s.Length - 1);
Console.WriteLine("Running " + i + " of" + directoriesToRename.Count());
Console.WriteLine("Renaming started for " + s);
p.StartInfo = new ProcessStartInfo(tfsTool, param)
{
UseShellExecute = false
};
p.Start();
p.WaitForExit();
Console.WriteLine("Renaming Complete for " + s);
Console.WriteLine("-----------------------------------------------------------");
File.AppendAllText(#"c:\log.txt", s + Environment.NewLine);
}
}

Cannot add row to spreadsheet

var ssNew = SpreadsheetApp.open('Student Files Data').getId();
var ss = SpreadsheetApp.openById(ssNew);
var sheet = ss.getSheetByName('Sheet1');
sheet.appendRow(["a man", "a plan", "panama"]);
I can't seem to get this to work. What am I missing?
The issue is the first line; the open() method expects a file object, not the file name as a string. Use the DriveApp getFilesByName method, which will return a file iterator, and next() will return the first match.
var ssNew = DriveApp.getFilesByName("Student Files Data").next().getId;

Why doesn't this Lua pattern work?

local querycreate = "create user 'dddqwd123_dwqd'#'localhost'"
local create, usercreate, username, userhost = querycreate:match("^(%w+)%s+(%w+)%s+\'(%w)\'#\'(%w)\'$")
print(string.format("query: %s", querycreate))
print(string.format(" var create = %s \n var usercreate = %s \n var username = %s \n var userhost = %s", create, usercreate, username, userhost))
query: create user 'dddqwd123_dwqd'#'localhost'
var create = nil
var usercreate = nil
var username = nil
var userhost = nil
My regex works fine on http://regexr.com?37voi.
If I change it to ("^(%w+)%s+(%w+)%s+"), it outputs:
var create = create
var usercreate = user
var username = nil
var userhost = nil
If I remove quotes from querycreate by setting it to "create user dddqwd123_dwqd # localhost" and use ^(%w+)%s+(%w+)%s+(%w+) # (%w+)$, then the output is normal.
Your initial pattern:
"^(%w+)%s+(%w+)%s+\'(%w)\'#\'(%w)\'$"
The last two captures in your pattern lack + specifiers to indicate that they are to read 1 or more characters.
_ is not a word character matched by %w. You will need a character class including _ everywhere you would need to match it.
The escaping of ' within a "-quoted string is unnecessary.
With some improvement:
"^(%w+)%s+(%w+)%s+'([%w_]+)'#'([%w_]+)'$"
Alternatively: If you wanted to match anything within a set of quotes ', you could match against its inverse class:
"^(%w+)%s+(%w+)%s+'([^']*)'#'([^']*)'$"
([^']*) will capture anything (including nothing) that isn't ', until the end of the string or a ' is found.
You are missing the + on the parts of the pattern that match the user and domain.
You have "^(%w+)%s+(%w+)%s+\'(%w)\'#\'(%w)\'$"
You need "^(%w+)%s+(%w+)%s+'([%w_]+)'#'([%w_]+)'$" (removed unnecessary single quote escaping and to incorporate #RyanStein's comment about _).

Resources