I'm working on an automation task in PowerShell that extracts the contents of several .tar archives to their respective subfolders using recursion and the 7z.exe utility.
Im running into an issue 开发者_运维问答where the output dumps in my working directory instead of the subdirectory gci -r found the original tarball.
So far I have:
$files=gci -r | where {$_.Extension -match "tar"}
foreach ($files in $files) {
c:\7z.exe e -y $file.FullName }
Advice on setting the working directory within the loop or 7z tips are appreciated.
I am totally totally clueless when it comes to powershell, but after downloading an enormous torrent full of subdirectories ("publisher.title.author.year" essentially) each containing one or more zip files, which when unzipped each contained a part of a multi-file rar arhive, and FINALLY once assembled that contained a (uselessly named) pdf file...
so I came up with this rough and ready script to recurse into each subdirectory, unzip the zips into that directory, then assemble the rar files and extract the pdf into that directory, then rename the pdf with the directory name, and move it up a directory (so by the end I ended up with the base directory full of meaningfully named pdf files...
anyway - like I said I have literally no powershell knowledge so I'm mainly posting this because I wasted two hours writing it (I could have done it in 5-10 minutes in python or perl :P) and because if it's on the net I might actually find it again if I need to hehe
$subdirs = Get-ChildItem | ?{$_.Attributes -match 'Directory'}
foreach ($dir in $subdirs) {
cd $dir
$zip get-childitem | where {$_.Extension -match "zip"}
C:\7z.exe x -y $zip.FullName
$rar = get-childitem | where { $_.Extension -match "rar"}
C:\7z.exe x -y $rar
$pwd = get-item .
$newname = $pwd.basename+".pdf"
get-childitem *.pdf | rename-item -newname $newname
move-item $newname ..\
cd ..
}
Few points:
1) Use x
flag instead of e
to preserve paths.
2) Use -o
to specify destination / output. I am taking the destination folder to be the name of the tar file ( without extension ) and the path to be the same as the tar file. You can remove the folder and just have the path.
3) You are just using gci -r
- it will look for the files in the current directory. I have included $scriptDir
below, which will under the directories the script's path. To search entire machine, do something like gci c:\ -r
This is how I will do it:
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$z ="7z.exe"
$files=gci $scriptDir -r | where {$_.Extension -match "tar"}
foreach ($file in $files) {
$source = $file.FullName
$destination = Join-Path (Split-Path -parent $file.FullName) $file.BaseName
write-host -fore green $destination
$destination = "-o" + $destination
& ".\$z" x -y $source $destination
}
Give this a try. Performance tip, use the Filter parameter instead of where-object.
gci -r -filter *.tar | foreach { c:\7z.exe x -y $_.FullName $_.DirectoryName }
I'm the OP (made a new acct). Thanks manojlds, I changed
$destination = Join-Path (Split-Path -parent $file.FullName) $file.BaseName
to
$destination = Join-Path (Split-Path -parent $file.FullName) $file.DirName
in order to output to the same directory as the archive and maintain the tree structure. I also tweaked
$z ="7z.exe"
...
& ".\$z" x -y $source $destination
to
$z="c:\7z.exe"
...
& "$z" x -y $source $destination
because it was throwing an error (7z issue?).
Thanks much.
精彩评论