user2305193
user2305193

Reputation: 2059

create file index manually using powershell, tab delimited

Sorry in advance for the probably trivial question, I'm a powershell noob, please bear with me and give me advice on how to get better.

I want to achieve a file index index.txt that contains the list of all files in current dir and subdirs in this format:

./dir1/file1.txt   07.05.2020 16:16   1959281

where

  1. dirs listed are relative (i.e. this will be run remotely and to save space, the relative path is good enough)
  2. the delimiter is a tab \t
  3. the date format is day.month.fullyear hours:minutes:seconds, last written (this is the case for me, but I'm guessing this would be different on system setting and should be enforced)
  4. (the last number is the size in bytes)

I almost get there using this command in powershell (maybe that's useful to someone else as well):

 get-childitem . -recurse  | select fullname,LastWriteTime,Length | Out-File index.txt

with this result

FullName                                     LastWriteTime       Length
--------                                     -------------       ------
C:\Users\user1\Downloads\test\asdf.txt       07.05.2020 16:19:29   1490
C:\Users\user1\Downloads\test\dirtree.txt    07.05.2020 16:08:44      0
C:\Users\user1\Downloads\test\index.txt      07.05.2020 16:29:01      0
C:\Users\user1\Downloads\test\test.txt       07.05.2020 16:01:23    814
C:\Users\user1\Downloads\test\text2.txt      07.05.2020 15:55:45   1346

So the questions that remain are: How to...

  1. get rid of the headers?
  2. enforce this date format?
  3. tab delimit everything?
  4. get control of what newline character is used (\n or \r or both)?

Upvotes: 0

Views: 722

Answers (2)

Theo
Theo

Reputation: 61178

If the path you are running this from is NOT the current scrip path, do:

$path = 'D:\Downloads' # 'X:\SomeFolder\SomeWhere'
Set-Location $path

first.

Next, this ought to do it:

Get-ChildItem . -Recurse -File  | ForEach-Object {
    "{0}`t{1:dd.MM.yyyy HH:mm}`t{2}" -f ($_ | Resolve-Path -Relative), $_.LastWriteTime, $_.Length
} | Out-File 'index.txt'

On Windows the newline will be \r\n (CRLF)

If you want control over that, this should do:

$newline = "`n"   # for example
# capture the lines as string array in variable $lines
$lines = Get-ChildItem . -Recurse -File  | ForEach-Object {
    "{0}`t{1:dd.MM.yyyy HH:mm}`t{2}" -f ($_ | Resolve-Path -Relative), $_.LastWriteTime, $_.Length
}
# join the array with the chosen newline and save to file
$lines -join $newline | Out-File 'index.txt' -NoNewline

Because your requirement is to NOT have column headers in the output file, I'm using Out-File here instead of Export-Csv

Upvotes: 1

Olaf
Olaf

Reputation: 5242

Another approach could be this:

$StartDirectory = Get-Location
Get-ChildItem -Path $StartDirectory -recurse | 
    Select-Object -Property @{Name='RelPath';Expression={$_.FullName.toString() -replace [REGEX]::Escape($StartDirectory.ToString()),'.'}},
                            @{Name='LastWriteTime';Expression={$_.LastWriteTime.toString('dd.MM.yyyy HH:mm:ss')}},
                            Length | 
                                Export-Csv -Path Result.csv -NoTypeInformation -Delimiter "`t"

I recommend to use proper CSV files if you have structured data like this. The resulting CSV file will be saved in the current working directory.

Upvotes: 2

Related Questions