How can I rename multiple files like this:
file.txt , anotherfile.txt , log.txt
into something like this :
file1.txt , file2.txt , file3.txt
How can I do this in c# or in c++ ?
Use File.Move Method as:
IEnumerable<FileInfo> files = GetFilesToBeRenamed();
int i = 1;
foreach(FileInfo f in files)
{
File.Move(f.FullName, string.Format("file{0}.txt", i));
i++;
}
And if f is a fullpath, then you can do this instead:
File.Move(f.FullName,
Path.Combine(f.Directory.ToString(), string.Format("file{0}.txt", i));
This would work in you're using an sh-based shell:
#!/bin/sh
FEXT="txt" # This is the file extension you're searching for
FPRE="file" # This is the base of the new files names file1.txt, file2.txt, etc.
FNUM=1; # This is the initial starting number
find . -name "*.${FEXT}" | while read OFN ; do
# Determine new file name
NFN="${FPRE}${FNUM}.${FEXT}"
# Increment FNUM
FNUM=$(($FNUM + 1))
# Rename File
mv "${OFN}" "${NFN}"
done
The script in action:
[james#fractal renfiles]$ touch abc.txt
[james#fractal renfiles]$ touch test.txt
[james#fractal renfiles]$ touch "filename with spaces.txt"
[james#fractal renfiles]$ ll
total 4
-rw-rw-r-- 1 james james 0 Sep 3 17:45 abc.txt
-rw-rw-r-- 1 james james 0 Sep 3 17:45 filename with spaces.txt
-rwxrwxr-x 1 james james 422 Sep 3 17:41 renfiles.sh
-rw-rw-r-- 1 james james 0 Sep 3 17:45 test.txt
[james#fractal renfiles]$ ./renfiles.sh
[james#fractal renfiles]$ ll
total 4
-rw-rw-r-- 1 james james 0 Sep 3 17:45 file1.txt
-rw-rw-r-- 1 james james 0 Sep 3 17:45 file2.txt
-rw-rw-r-- 1 james james 0 Sep 3 17:45 file3.txt
-rwxrwxr-x 1 james james 422 Sep 3 17:41 renfiles.sh
In c++, you will eventually use
std::rename(frompath, topath);
to perform the action. TR2 proposal N1975 covers this function. However, until then, use boost::rename for the immediate future, and tr2::rename for the period after approval before final placement.
Loop through and use whatever names you want. Don't quite know if you're trying to add numbers, because the current question says 1, 2, 2.
In c# you can use File.Move(source, dest)
Of course you can do it programatically:
string[] files = new string[] {"file.txt" , "anotherfile.txt" , "log.txt"}:
int index = 0;
string Dest;
foreach (string Source in files)
{
if (!Files.Exists(Source )) continue;
do {
index++;
Dest= "file"+i+".txt";
} while (File.Exists(NewName);
File.Move(Source , Dest);
}
Related
This question already has answers here:
Reading CSV files using C#
(12 answers)
Closed last month.
I have a text file as below and I want to get only the numbers below column rank:
SKYRain LND(4) VA(x) ZZ(x) NUM(n) Rank ll ListOfNames
------- ------ ----- ----- ------ ---- -- -----------
1002 75 283680 185836 1,111.50 19268 1 Jack
4308 1100 175896 195404 751.70 6384 1 Sara
3070 252 1044788 884160 682.94 18924 1 Robert
3187 206 852280 97932 535.83 16472 1 Harry
I just want the numbers below the rank below:
19268
6384
18924
16472
Is there a way?
You have a fixed width text file. Just can simply use SubString():
public class Program{
public static void Main(){
string aLineOfYourTextFile = " 1002 75 283680 185836 1,111.50 19268 1 Jack ";
Console.WriteLine(aLineOfYourTextFile.Substring(48,5));
}
}
You can also use Split():
public class Program{
public static void Main(){
string aLineOfYourTextFile = " 1002 75 283680 185836 1,111.50 19268 1 Jack ";
var columns = aLineOfYourTextFile.Split(new[]{" "}, StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine(columns[5]);
}
}
read and skip 2 lines
read next line, split on " ", select 5th entry, convert to int
repeat above till EOF
I need to export Entities to a CSV File using CSVHelper. I made a trial work but I would have to write every field manually. What I want is to Write a record Prepended with either an 'H' or a 'D' and end every line with a single space. My Demo models:
PersonId FirstName LastName DateOfBirth
1 Randy Smith 1968-08-31
2 Zachary Smith 2002-01-10
3 Angie Smith 1969-11-20
4 Khelzie Smith 1996-07-27
AutoId Year Make Model OwnerId
1 2000 Toyota 4Runner 1
2 1995 Ford Mustang 1
3 2014 Chevrolet Corvette Stingray Coupe 2
4 2014 Volkswagen Beetle Coupe 4
5 1980 Ford F-150 2
6 1968 Chevrolet Camaro 3
7 2000 Tonka Truck 3
8 1993 Honda Accord 4
Into a CSV File Like this:
H 1 Randy Smith 8/31/1968
D 1 2000 Toyota 4Runner
D 2 1995 Ford Mustang
H 2 Zachary Smith 1/10/2002
D 3 2014 Chevy Corevett
D 5 1980 Ford F-150
H 3 Angie Smith 11/20/1969
D 6 1968 Chevrolet Camaro
D 7 2000 Tonka Truck
H 4 Khelzie Smith 7/27/1996
D 4 2014 Volkswagen Beetle Coupe
This is the Code I finally got to work:
StreamWriter textWriter = File.CreateText(fileName);
var csv = new CsvWriter(textWriter);
csv.Configuration.Delimiter = delimiter;
csv.Configuration.QuoteNoFields = true;
// This will skip those people who don't own a vehicle
foreach (Person person in people.Where(person => person.Vehicles.Count > 0))
{
// The letter 'H' must prefix every Header line
csv.WriteField((#"H " + person.PersonId));
csv.WriteField(person.FirstName);
csv.WriteField(person.LastName);
// Headers lines must end with a single space.
csv.WriteField((person.DateOfBirth.ToShortDateString() + " "));
csv.NextRecord();
foreach (Automobile auto in person.Vehicles)
{
// The letter 'D' must prefix every Detail line
csv.WriteField((#"D " + auto.AutoId));
csv.WriteField(auto.Year);
csv.WriteField(auto.Make);
// Details lines must end with a single space.
csv.WriteField((auto.Model + " "));
csv.NextRecord();
}
}
The real tables have ~70 fields apiece.
Just for those that have as thick a skull as mine, here is a solution:
foreach (TransactionHeader header in headers)
{
csv.WriteField("H");
csv.WriteRecord(header);
csv.WriteField(" ");
csv.NextRecord();
foreach (TransactionDetail detail in header.TransactionDetail)
{
csv.WriteField("D");
csv.WriteRecord(detail);
csv.WriteField(" ");
csv.NextRecord();
}
}
Thanks to everyone who saw this as pretty obvious and patiently waited for me to bash my head down on my desk enough times and then figure this out myself.
The snippet below detects from a list of files which of them is a Directory on Ftp
as C# it will be like below
var files = new List<string>(){"App_Data", "bin", "Content"};
var line = "drwxr-xr-x 1 ftp ftp 0 Mar 18 22:41 App_Data"
var dir = files.First(x => line.EndsWith(x));
How I can transalte the last line in PowerShell ?
Something like this...
$files = #("App_Data", "bin", "Content")
$line = "drwxr-xr-x 1 ftp ftp 0 Mar 18 22:41 App_Data"
$dir = $files | Where { $line.EndsWith($_) } | Select -First 1
These versions of the last line would all accomplish the same:
$dir = #($files | Where { $line.EndsWith($_) })[0]
$dir = $files | Where { $line.EndsWith($_) } | Select -index 0
$dir = $files | Where { $line.EndsWith($_) } | Select -First 1
It was pointed out that the above is not exactly equivalent in behavior to Linq.First because Linq.First throws exceptions in two cases:
Throws ArgumentNullException when source or predicate is null.
Throws InvalidOperationException when source sequence is empty or no element satisfies the condition in predicate.
If you wanted that behavior exactly, you'd need some extra guard code.
as Robert Groves said, Select-Object -First Occurence do the tricks, you can also use -Last Occurence.
by the way, like any other static .Net method you can use linq in powershell.
[Linq.Enumerable]::First($list)
[Linq.Enumerable]::Distinct($list)
[Linq.Enumerable]::Where($list, [Func[int,bool]]{ param($item) $item -gt 1 })
Doug Finke produced a great video ( only 7 mins ) about converting C# to Powershell
http://dougfinke.com/video/CSharpToPowerShell.html
Roberts example is very good indeed, though comma delimiting will implicitly be treated as an array
the shortest way of doing it would be to put it all into a single pipeline :
$dir = "App_Data", "bin", "Content" | % { if("drwxr-xr-x 1 ftp ftp 0 Mar 18 22:41 App_Data".EndsWith($_)) { $_ } } | select -first 1
There is a native way to do this using the Powershell Array's Where Function by passing in a WhereOperatorSelectionMode like this:
(1..9).Where({ $_ -gt 3}, "First") # 4
You can also use the mode straight from the enum as well:
$mode = [System.Management.Automation.WhereOperatorSelectionMode]::First
(1..9).Where({ $_ -gt 3}, $mode) # 4
Using any of the values from the WhereOperatorSelectionMode enum
Name
Val
Description
Default
0
Return all items
First
1
Return the first item
Last
2
Return the last item
SkipUntil
3
Skip items until condition is true
Until
4
Return all items until condition is true
Split
5
Return an array of two elements
See Also: Checking Out The Where and ForEach Operators in PowerShell V4
This is a really simple implementation for First:
function First($collection)
{
foreach ($item in $collection)
{
return $item
}
return $null
}
Instead of returning $null, you could throw an InvalidOperationException exception.
I have a C# console program which main functions should let a user grep lines / columns from a log text file.
An Example within the text file the user wishes to grep a group of all the related lines starting from a particular date etc. "Tue Aug 03 2004 22:58:34" to "Wed Aug 04 2004 00:56:48". Therefore after processing, the program would then output all the data found within the log text files between the 2 dates.
Could someone please advise on some codes that I could use to grep or create a filter to retrieve the neccessary text/data from the file? Thanks!
C# Program Files:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
namespace Testing
{
class Analysis
{
static void Main()
{
// Read the file lines into a string array.
string[] lines = System.IO.File.ReadAllLines(#"C:\Test\ntfs.txt");
System.Console.WriteLine("Analyzing ntfs.txt:");
foreach (string line in lines)
{
Console.WriteLine("\t" + line);
// ***Trying to filter/grep out dates, file size, etc****
if (lines = "Sun Nov 19 2000")
{
Console.WriteLine("Print entire line");
}
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
}
Log Text File Example:
Wed Jul 21 2004 16:58:48 499712 m... r/rrwxrwxrwx 0 0 8360-128-3
C:/Program Files/AccessData/Common Files/AccessData LicenseManager/LicenseManager.exe
Tue Aug 03 2004 22:58:34 23040 m... r/rrwxrwxrwx 0 0 8522-128-3
C:/System Volume Information/_restore{88D7369F-4F7E-44D4-8CD1-
F7FF1F6AC067}/RP4/A0002101.sys
23040 m... r/rrwxrwxrwx 0 0 9132-128-3
C:/WINDOWS/system32/ReinstallBackups/0003/DriverFiles/i386/mouclass.sys
23040 m... r/rrwxrwxrwx 0 0 9135-128-4 C:/System Volume
Information/_restore{88D7369F-4F7E-44D4-8CD1-F7FF1F6AC067}/RP4/A0003123.sys
23040 m... r/rrwxrwxrwx 0 0 9136-128-3
C:/WINDOWS/system32/drivers/mouclass.sys
Tue Aug 03 2004 23:01:16 196864 m... r/rrwxrwxrwx 0 0 4706-128-3
C:/WINDOWS/system32/drivers/rdpdr.sys
Tue Aug 03 2004 23:08:18 24960 m... r/rrwxrwxrwx 0 0 8690-128-3
C:/WINDOWS/system32/drivers/hidparse.sys
You could do this using Regex to select matching lines in a richer way than string.Contains allows.
Not sure why you are reinventing findstr.exe though.
For large files you might find File.ReadLines (.Net 4 only) performs better - this reads the same lines but allows you to process them in a foreach and other IEnumerable scenarios without loading the entire file into RAM at once.
Well, as a quick fix for the specific example:
if (line.StartsWith("Sun Nov 19 2000"))
{
Console.WriteLine(line);
}
You could use Contains to find a substring within the line.
Note that loading the whole file in an array won't scale well for very large logs. We can look into fixing that if it's an issue for you - but let's take things slowly :)
Here's a grep style method I use in testing:
public static List<string> FileGrep(string filePath, string searchText)
{
var matches = new List<string>();
using (var f = File.OpenRead(filePath))
{
var s = new StreamReader(f);
while (!s.EndOfStream)
{
var line = s.ReadLine();
if (line != null && line.Contains(searchText)) matches.Add(line);
}
f.Close();
}
return matches;
}
I have a block of text that im taking from a Gedcom (Here and Here) File
The text is flat and basically broken into "nodes"
I am splitting each node on the \r char and thus subdividing it into each of its parts( amount of "lines" can vary)
I know the 0 address will always be the ID but after that everything can be anywhere so i want to test each Cell of the array to see if it contains the correct tag for me to proccess
an example of what two nodes would look like
0 #ind23815# INDI <<<<<<<<<<<<<<<<<<< Start of node 1
1 NAME Lawrence /Hucstepe/
2 DISPLAY Lawrence Hucstepe
2 GIVN Lawrence
2 SURN Hucstepe
1 POSITION -850,-210
2 BOUNDARY_RECT (-887,-177),(-813,-257)
1 SEX M
1 BIRT
2 DATE 1521
1 DEAT Y
2 DATE 1559
1 NOTE * Born: Abt 1521, Kent, England
2 CONT * Marriage: Jane Pope 17 Aug 1546, Kent, England
2 CONT * Died: Bef 1559, Kent, England
2 CONT
1 FAMS #fam08318#
0 #ind23816# INDI <<<<<<<<<<<<<<<<<<<<<<< Start of Node 2
1 NAME Jane /Pope/
2 DISPLAY Jane Pope
2 GIVN Jane
2 SURN Pope
1 POSITION -750,-210
2 BOUNDARY_RECT (-787,-177),(-713,-257)
1 SEX F
1 BIRT
2 DATE 1525
1 DEAT Y
2 DATE 1609
1 NOTE * Born: Abt 1525, Tenterden, Kent, England
2 CONT * Marriage: Lawrence Hucstepe 17 Aug 1546, Kent, England
2 CONT * Died: 23 Oct 1609
2 CONT
1 FAMS #fam08318#
0 #ind23817# INDI <<<<<<<<<<< start of Node 3
So a when im done i have an array that looks like
address , string
0 = "1 NAME Lawrence /Hucstepe/"
1 = "2 DISPLAY Lawrence Hucstepe"
2 = "2 GIVN Lawrence"
3 = "2 SURN Hucstepe"
4 = "1 POSITION -850,-210"
5 = "2 BOUNDARY_RECT (-887,-177),(-813,-257)"
6 = "1 SEX M"
7 = "1 BIRT "
8 = "1 FAMS #fam08318#"
So my question is what is the best way to search the above array to see which Cell has the SEX tag or the NAME Tag or the FAMS Tag
this is the code i have
private int FindIndexinArray(string[] Arr, string search)
{
int Val = -1;
for (int i = 0; i < Arr.Length; i++)
{
if (Arr[i].Contains(search))
{
Val = i;
}
}
return Val;
}
But it seems inefficient because i end up calling it twice to make sure it doesnt return a -1
Like so
if (FindIndexinArray(SubNode, "1 BIRT ") != -1)
{
// add birthday to Struct
I.BirthDay = SubNode[FindIndexinArray(SubNode, "1 BIRT ") + 1].Replace("2 DATE ", "").Trim();
}
sorry this is a longer post but hopefully you guys will have some expert advice
Can use the static method FindAll of the Array class:
It will return the string itself though, if that works..
string[] test = { "Sex", "Love", "Rock and Roll", "Drugs", "Computer"};
Array.FindAll(test, item => item.Contains("Sex") || item.Contains("Drugs") || item.Contains("Computer"));
The => indicates a lamda expression. Basically a method without a concrete implementation.
You can also do this if the lamda gives you the creeps.
//Declare a method
private bool HasTag(string s)
{
return s.Contains("Sex") || s.Contains("Drugs") || s.Contains("Computer");
}
string[] test = { "Sex", "Love", "Rock and Roll", "Drugs", "Computer"};
Array.FindAll(test, HasTag);
What about a simple regular expression?
^(\d)\s=\s\"\d\s(SEX|BIRT|FAMS){1}.*$
First group captures the address, second group the tag.
Also, it might be quicker to dump all array items into a string and do your regex on the whole lot at once.
"But it seems inefficient because i end up calling it twice to make sure it doesnt return a -1"
Copy the returned value to a variable before you test to prevent multiple calls.
IndexResults = FindIndexinArray(SubNode, "1 BIRT ")
if (IndexResults != -1)
{
// add birthday to Struct
I.BirthDay = SubNode[IndexResults].Replace("2 DATE ", "").Trim();
}
The for loop in method FindIndexinArray shd break once you find a match if you are interested in only the first match.