Author Posts

January 1, 2012 at 12:00 am

by brycspain at 2013-03-22 12:12:25

I'm trying add .pdf file names in a directory and add their names with a little extra in a .dat file in the same directory. (Don't ask, I'm doing this for a customer at work)

I have this input and I'm working from the c:\test\ directory:

123456.pdf
234567.pdf
345678.pdf
456789.pdf

I need the output to look like this:

RM – EMAR, 123456, 123456.pdf
RM – EMAR, 234567, 234567.pdf
etc.

The output I'm getting from my script is:

RM – EMAR,123456,c:\test\123456.pdf
etc.

I'm just not sure how to get rid of the c:\test\ portion of the filename output. I've tried all sorts of things and can't get it to behave the way I want.

Any help would be appreciated.

$RM = "RM - EMAR"
$Date = Get-Date
$File = "{0:yyyyMMddHHmm}EMAR.DAT" -f (Get-Date)
$FileName = New-Item -name $File -type file -force

Get-ChildItem * -Include *.pdf | %{ $id = $_.Name.SubString(0,6)
Add-Content $FileName $RM","$id","$_
}

by ArtB0514 at 2013-03-22 12:47:18

Try $_.BaseName in your foreach clause following Get-ChildItem

Get-Help Get-ChildItem -Parameter BaseName

by MasterOfTheHat at 2013-03-22 13:14:06

Well, BaseName is not a parameter of Get-ChildItem. The op would need to look at the properties of the FileInfo object to look at the BaseName and Name parameters to see which one is what he is actually looking for. So changing the last line of this script to something like this would give him the output he's looking for:
Add-Content $FileName $RM","$id","$_
This problem doesn't make a lot of sense to me, though. I see that brycspain is trying to include the $_ object as part of a string, so posh is going to call the ToString() method of the object. But When I try to validate that, I get mixed results:
PS > gci -path c:\temp\test\* | %{ $_.toString() }
C:\temp\test\201303221447EMAR.DAT
C:\temp\test\DepartmentName-00-22-64-F4-8E-0C.TIF
PS > gci -path c:\temp\test\ | %{ $_.toString() }
201303221447EMAR.DAT
DepartmentName-00-22-64-F4-8E-0C.TIF

What difference does the wildcard make? If you run Get-Member on the returned object from both commands, you see that they are all FileInfo objects, so they should use the same ToString() method, right?
gci -path c:\temp\test\ | %{ $_ | gm }
gci -path c:\temp\test\* | %{ $_ | gm }

by brycspain at 2013-03-27 01:44:34

I'm actually needing to trim the first 6 characters from the filenames. The sample filenames are only 6 characters but they could be longer. Changing to a string gives me errors.

$RM = "RM - EMAR"
$Date = Get-Date
$File = "{0:yyyyMMddHHmm}EMAR.DAT" -f (Get-Date)
$FileName = New-Item -name $File -type file -force

gci * -Include *.pdf | %{ $_.toString() } | %{ $id = $_.Name.SubString(0,6)
Add-Content $FileName $RM","$id","$_
}

You cannot call a method on a null-valued expression.
At line:1 char:48
+ gci * -Include *.pdf | %{ $_.toString() } | %{ $id = $_.Name.SubString(0,6)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

When I run these: gci -path c:\temp\test\ | %{ $_ | gm }
gci -path c:\temp\test\* | %{ $_ | gm }

I get a very large output with over 100 properties and methods. Looks like I get the same output from both lines of code.

Is there a better way to do what I'm trying to do?

by brycspain at 2013-03-27 06:38:10

Just noticed something....This code won't work because once you convert to a string you can't pipeline the output correct?

gci * -Include *.pdf | %{ $_.toString() } | %{ $id = $_.Name.SubString(0,6)

by poshoholic at 2013-03-27 07:01:59

Actually, what that code does is the following:
1. Stage 1 of the pipeline, get pdf files (by the way, I would use -Filter *.pdf instead of -Include *.pdf for this; right now I forget why though).
2. Stage 2, convert the file to a string.
3. Stage 3, take the string and try to access a Name property. Name does not exist as a property on the string.

You should get rid of the middle stage where you convert the file to a string so that the following stage can properly access the Name property of the file objects.

by MasterOfTheHat at 2013-03-27 08:42:53

[quote="MasterOfTheHat"]... So changing the last line of this script to something like this would give him the output he's looking for:
Add-Content $FileName $RM","$id","$_ ...
[/quote]
I obviously copy/pasted the wrong line here... sorry about that. I think what I was going for was:
Add-Content -Path $FileName -Value "$RM,$id,$_"
[quote="brycspain"]Just noticed something....This code won't work because once you convert to a string you can't pipeline the output correct?

gci * -Include *.pdf | %{ $_.toString() } | %{ $id = $_.Name.SubString(0,6)[/quote]
And you're mostly right here. It doesn't work because you convert the file to a string and then pass the string down the pipeline to the next loop. When you try to access a Name property in that loop, it is trying to find a property on the System.String object called "Name", and one doesn't exist. Poshoholic is right, just remove the middle step. (I think my secondary question about the wildcard confused you.)
[quote="poshoholic"]...
1. Stage 1 of the pipeline, get pdf files (by the way, I would use -Filter *.pdf instead of -Include *.pdf for this; right now I forget why though).
...
[/quote]
Maybe because of this from the help docs?
[quote]The Include parameter is effective only when the command includes the Recurse parameter or the path leads to the
contents of a directory, such as C:\Windows\*, where the wildcard character specifies the contents of the
C:\Windows directory.[/quote]
From my understanding, -Include causes powershell to retrieve all of the objects and then filter it, but -Filter actually uses the file provider to actually only retrieve certain objects. Makes it more efficient.

by DonJ at 2013-03-27 08:45:45

You're correct on -Include and -Filter.

by brycspain at 2013-03-27 08:57:00

I'm very thankful for the help and the scripting lesson. Still getting the wrong output though...am I missing something?

RM – EMAR,100367,C:\test\10036745678.PDF
RM – EMAR,101657,C:\test\10165745678.PDF
RM – EMAR,102352,C:\test\10235245678.PDF
RM – EMAR,103464,C:\test\10346445678.PDF
RM – EMAR,104698,C:\test\10469845678.PDF
RM – EMAR,106551,C:\test\10655145678.PDF

$RM = "RM - EMAR"
$Date = Get-Date
$File = "{0:yyyyMMddHHmm}EMAR.DAT" -f (Get-Date)
$FileName = New-Item -name $File -type file -force

gci * -filter *.pdf | %{ $id = $_.Name.SubString(0,6)
Add-Content $FileName -Value "$RM,$id,$_"
}

by MasterOfTheHat at 2013-03-27 09:13:08

It's doing exactly what you told it to! 🙂 Use "$RM,$id,$_.Name"

by brycspain at 2013-03-27 09:37:38

Now it's appending the .name on the end of the filename

RM – EMAR,100367,C:\test\10036745678.PDF.name

$RM = "RM - EMAR"
$Date = Get-Date
$File = "{0:yyyyMMddHHmm}EMAR.DAT" -f (Get-Date)
$FileName = New-Item -name $File -type file -force

gci * -filter *.pdf | %{ $id = $_.Name.SubString(0,6)
Add-Content $FileName -Value "$RM,$id,$_.name"
}

by MasterOfTheHat at 2013-03-27 09:41:11

My fault! "$RM,$id,$($_.Name)" may do it...

by brycspain at 2013-03-27 09:53:59

Posh did an excellent job (The third person stuff cracks me up). Thanks for your help and thanks to Don for peeking his head in on the thread.

The winning code is:

$RM = "RM - EMAR"
$Date = Get-Date
$File = "{0:yyyyMMddHHmm}EMAR.DAT" -f (Get-Date)
$FileName = New-Item -name $File -type file -force

gci * -filter *.pdf | %{ $id = $_.Name.SubString(0,6)
Add-Content $FileName -Value "$RM,$id,$($_.name)"
}

by brycspain at 2013-03-27 12:07:19

Sorry Master...I saw Posh in the thread and assumed it was you.

Thanks a ton for helping me.

by MasterOfTheHat at 2013-03-27 13:21:10

No worries! He's smarter than me, anyway! 😉