Can I do this with cmd?
for example
c:\a\a1\qw.exe => c:\a1\qw.exe like that
I have many directories like that so I want to learn how can I do this in windows?
I want to move many folders in one command
Thank you for your answer
You can combine move with two for /d loops:
for /d %i in (?) do for /d %j in ("%i\*.*") do move "%j" .
The first loop will find all directories with a single character (? will match a, b) below the current directory. The second loop will find all directories (*.* will match everything) in these directories and move it to the current directory.
Replace ? by *.* if you don't have single letter directories. But be warned: do not run this in C:\, or it will attempt to move all folders out of the Windows and Program Files directory.
The Move Command allows users to transfer files or directories from one directory to another, or from one drive to another.
https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/move
move /?
Example of Move Command
To move the files of c:\windows\test to the test directory in the root directory, this is of course assuming you have the Windows\test directory.
move c:\windows\test\*.* c:\test
Powershell Move-Item
The Move-Item cmdlet moves an item, including its properties, contents, and child items, from one location to another location. The locations must be supported by the same provider. For example, it can move a file or subdirectory from one directory to another or move a registry subkey from one key to another. When you move an item, it is added to the new location and deleted from its original location.
https://social.technet.microsoft.com/Forums/en-US/729f90e2-4c1d-445d-ad72-6f752a3d7d24/powershell-move-folder-and-subfolders
Example Using PowerShell Move-Item
$parentpath = "C:\Temp"
$files = Get-ChildItem -Path $parentpath -Filter "*.txt" -Recurse
Set-Location $parentpath
New-Item -Name "test" -ItemType Directory -ErrorAction SilentlyContinue
Set-Location .\test
foreach ($file in $files)
{
$destination = New-Item -ItemType directory -Name $(split-path $file.Directory -Leaf) -erroraction 'silentlycontinue'
$file | Move-Item -Destination $destination
}
Bit-Transfer
My Bit-Transfer script is here. I would place it here for you, but some start complaining that I copied my own script to this post.
backup www directory from local to network drive powershell
Here You Go Using WhatIf -- 'd:\deneme\a\a1', 'd:\deneme\b\b1', 'd:\deneme\c\c1' one level up 'd:\deneme\a1', 'd:\deneme\b1', 'd:\deneme\c1'
$paths = "d:\deneme\a\a1", "d:\deneme\b\b1", "d:\deneme\c\c1"
ForEach($path in $paths) {
$path = $path.ToString()
$up = $path.Substring(0, $path.lastIndexOf('\'))
#Move-Item -Path $path -Destination $up -force -Verbose
Move-Item -Path $path -Destination $up -WhatIf
}
Related
Currently I have a directory tree system like the image:
I would like someone to help me create a small piece of code. I want to search all directories, I will see a folder named "C" as above, copy all the data and rename it to a higher level folder, will copy to another folder with the name E . You can only copy the A1 folder and contain the C folder inside. I'm using windows 10. Thank you very much.
In PowerShell, the Copy-Item cmdlet can rename an item while copying. So you want to:
Use Get-ChildItem to find all subfolders of the source named "C".
Pipe these to Copy-Item
Construct the destination path and name using Join-Path.
$Source = 'C:\Source' ### Parent folder of folders "A", "B", etc.
$Dest = 'D:\Dest' ### Destination path for copied folders
# Destination root must exist:
If (!(Test-Path $Dest)) {mkdir $Dest | out-null}
Get-ChildItem -Path $Source -Filter 'C' -Directory -Recurse |
Copy-Item -Destination {Join-Path $Dest $_.Parent.Name} -Recurse
Which can be shortened using positional parameters and aliases to:
gci $Source 'C' -ad -s |
copy -Dest {Join-Path $Dest $_.Parent.Name} -Recurse
I'm trying to copy all of the cover.jpg files in my music library to one folder. My attempts so far have either landed me with one file in the destination, or every desired file but also in their own folder matching the source (i.e. folders named for each album containing just the cover.jpg file).
Get-ChildItem "C:\Music" -recurse -filter *.jpg | Copy-Item -Destination "C:\Destination"
I realised that the copy-item command was simply overwriting the previous copies thus leaving me with only one file. I then tried going down the renaming route by moving the file then renaming it but of course that failed as the folder I was basing the rename off has now changed. I don't want to change the name of the file before I copy it as other programs still need the cover.jpg to function.
My question is...
Does anybody know how to recursively look through each folder in my music library to find the cover.jpg file, rename it to match the parent folder (or even if possible, grandparent and parent) then copy that file to a new folder making sure to not copy or create any new folders in this destination?
As a bonus, could this check if a file already exists so that if I ran it in the future only new files will be copied?
The file structure for the library is pretty simple. \Music\Artist\Album title\cover.jpg
If you have a music library structure like that, the easiest way would be to use the properties Directory and Parent each FileInfo object returned by Get-ChildItem contains:
$sourcePath = 'C:\Music'
$destination = 'C:\Destination'
# if the destination folder does not already exist, create it
if (!(Test-Path -Path $destination -PathType Container)) {
$null = New-Item -Path $destination -ItemType Directory
}
Get-ChildItem -Path $sourcePath -Filter '*.jpg' -File -Recurse | ForEach-Object {
$newName = '{0}_{1}_{2}' -f $_.Directory.Parent.Name, $_.Directory.Name, $_.Name
$_ | Copy-Item -Destination (Join-Path -Path $destination -ChildPath $newName)
}
I have multiple zip files.
They are called folder(1).zip, folder(2).zip, folder(3).zip. Using PowerShell, when I attempt to unzip them all into unique folders using this...
Get-ChildItem 'c:\users\name\downloads' -Filter *.zip | Expand-Archive -DestinationPath 'c:\users\name\downloads' -Force
I get all of the files into one folder called "folder". How can I get the zip folders to unzip into separate folders?
Bonus question, is there a way, as part of this process, to rename each folder as it's coming out so folder(1).zip becomes Name-Here, folder(2).zip becomes Other-Name-Here, etc?
Thanks!
Because you specify only one destination path they will all be extracted into c:\users\name\downloads. I suppose the zip archives each contain a folder named "folder", so all contents from all archives end up together in c:\users\name\downloads\folder
You would have to specify a different destination path for each archive. Not sure what your naming convention should be, I have used a simple counter:
$counter = 0
Get-ChildItem 'c:\users\name\downloads' -Filter *.zip | foreach {
$destination = Join-Path $_.DirectoryName ("YourName" + $counter++)
Expand-Archive $_.FullName -DestinationPath $destination
}
Of course I suppose, now every of those folders will have the subfolder "folder", but if that's how the archives are built there's not really a way to change that. If you are absolutely sure that all archives have that subfolder, you could do something like this:
$counter = 0
Get-ChildItem 'c:\users\name\downloads' -Filter *.zip | foreach {
# expand to the root folder first
Expand-Archive $_.FullName -DestinationPath $_.DirectoryName
# now rename the extracted "folder" to whatever you like
Rename-Item (Join-Path $_.DirectoryName "folder") -NewName ("YourName" + $counter++)
}
I have backup files sitting in a directory. The objective I am trying to achieve is that each time I run this piece of Powershell against that directory, I want it to move the files into a folder that gets created and append today's date to it. I have tried this:
Get-ChildItem -Path 'C:\API\APIBackups' | ForEach-Object {
Move-Item -Path $_.FullName -Destination "C:\Users\Admin\Desktop\New folder\$($_.BaseName,(Get-Date).ToString("MMddyyyy"),$_.Extension)"
}
All this does is moves the backup files into "New folder" and append the date to the files themselves. I'm wanting it to create a new folder with today's date appended within "New folder" and have the backup files sitting in there. Any help would be great.
For one the commas do not belong but each section of "code" needs their own subexpression. You are also sticking the date in between the base filename and the file extension, so it looks like you want to insert the date in the file name. Instead, you can adjust it to this.
Get-ChildItem -Path 'C:\API\APIBackups' | ForEach-Object {
Move-Item -Path $_.FullName -Destination "C:\Users\Admin\Desktop\New folder$((Get-Date).ToString("MMddyyyy"))\"
}
Unless you're renaming the file, you don't need to specify it in the path.
Important Note that if that folder does not exist, you will need to create it first. Otherwise you'll end up with an extensionless file with that name instead. You could test for the path first, create if it doesn't exist, then move.
Get-ChildItem -Path 'C:\API\APIBackups' | ForEach-Object {
$newfolder = "C:\Users\Admin\Desktop\New folder$((Get-Date).ToString("MMddyyyy"))\"
if(-not(Test-Path $newfolder)){
$null = New-Item -Path $newfolder -ItemType Directory
}
Move-Item -Path $_.FullName -Destination $newfolder
}
The $null is to hide the output that New-Item creates by default.
A suggestion for improvement would be to use Join-Path for building the new folder path
I'm trying to copy files using copy-item. Specifically, I want to copy files with a particular extension that are within a folder or its subfolders to another location, and to retain the subfolder hierarchy. I've tried using -filter and -include to specify the file extension, but no files are copied.
My source and destination paths are stored in variables $packageSourcePath and $objPath. When called, $packageSourcePath will be like the following ".\src\projects\Project1\PackageFiles" and $objPath will be like the following ".\bld\Project1\obj".
The command I've tried using is this:
Copy-Item -Path $packageSourcePath\* -Filter *.resw -Destination $objPath -Recurse
I've also tried variations, such as leaving off * from the path, or using -Include instead of -Filter. Nothing works. If I leave out the -Filter argument, then files copy, but all of the files are copied. I only want files with the particular extension.
I've given up on Copy-Item. JohnLBevan's answer didn't actually do what I want since all files in the source root get copied, even though they don't match the filter. I tried piping Convert-Path | Select-String | Copy-Item but still got all files in the source root being copied.
A contact in a different context provided a couple of suggestions:
1)
Get-ChildItem -Force -Recurse -ErrorAction Ignore -Path $packageSourcePath -Filter *.resw | % {
$src = $_.FullName
$dst = Join-Path $objPath $src.SubString($packageSourcePath.Length)
echo "copy ""$src"" ""$dst"""
}
I think this is a bit harder to follow, hence less maintainable for the next person (likely another PS-neophyte like me) a year from now. ("Why is the -ErrorAction parameter needed here? What's the behaviour of the Substring() method, and why can't I find that using Get-Help?")
This suggestion is a bit clearer, after re-familiarizing with attrib and checking the effect of the xcopy switches:
2)
cd $packageSourcePath
attrib -a /s
attrib +a *.resw /s
xcopy /eidlm $packageSourcePath $objPath
But if we're going to use xcopy, we don't need to call attrib:
xcopy $packageSourcePath*.resw $objPath /s /i > $null
The only problem with this for my scenario is that xcopy emits an error if no matching files are found. My script is being used for a VSTS build task, and the xcopy errors cause the build task to fail. (For that reason, I'm guess that suggestion 2 also wouldn't work for me.)
So, I've opted for this:
# In PS version 5.1, nothing gets copied using Copy-Item $packageSourcePath\* -Filter *.resw ...
# so resorting to using xcopy, which mostly works. The one issue is that xcopy will output an
# error if no matching file is found, so using GCI first to test for a matching file.
if ($(Get-ChildItem $packageSourcePath\*.resw -Recurse).count -gt 0) {
xcopy $packageSourcePath\*.resw $objPath /s /i > $null
}
The condition using GCI is added to check there are matching files before calling xcopy, thereby avoiding any errors.
I'm still amazed that Copy-Item -Filter -Recurse didn't work.
This should do it (obviously this could be done in 1 line; I've assigned values to the variables just to help make it readable / self-explanatory):
[string]$filter = '*.resw'
[string]$source = Join-Path -Path $packageSourcePath -ChildPath '*'
[string]$target = $objPath
$source | Convert-Path | Copy-Item -Filter $filter -Recurse -Destination $target -Container #-Force
Notes:
We append the asterisk to the source path to ensure that we copy the contents of the source folder to the destination, without copying the source's root folder into the destination (i.e. say we're copying c:\temp\from to c:\temp\to, we don't want c:\temp\to\from (unless it's a copy of c:\temp\from\from)).
We use the Join-Path cmdlet to append this asterisk to ensure the appropriate slashes are inserted into the path.
We do a Convert-Path on the source to resolve the asterisk to the child folder/file names... for some reason copy-item doesn't handle these asterisks well. NB: Convert-Path will potentially return an array of paths; i.e. if there's more than one file/subfolder directly under the source folder. Get-Item or Resolve-Path could equally be used for this; I prefer Convert-Path since it returns a simple string array, rather than a more complex type; but there's no strong argument for using any one over the others.
We pipe these source paths to the Copy-Item command so it can be applied to each path returned by Convert-Path.
We include -Recurse to say we're interested in anything in the subfolders of the copied path.
We include the -Container parameter to say that we want to preserve any folder structure when copying. Strictly this is not needed, as this switch is defaulted to true (i.e. rather we should specify if we don't want this behaviour: -Container:$false; but I like to be clear that I deliberately want to preserve the directory structure, as opposed to leaving the assumption that I may not have thought of this. There's a better explanation of this here: https://stackoverflow.com/a/21798660/361842.
You could optionally include -Force; this would mean that should an item of the same name already exist in the target we overwrite it instead of getting an error.
Related documentation:
Join-Path
Convert-Path
Copy-Item
Update 2018-01-03
Per comments, this solution should ensure that only those items you want get copied, and pre-existing directories shouldn't cause issues.
[string]$filter = '*.resw'
[string]$source = $packageSourcePath
[string]$target = $objPath
#copy all files in subfolders of the source
$source | Get-ChildItem -Directory | Copy-Item -Filter $filter -Recurse -Destination $target -Container -Force
#copy all files in root of the source
$source | Get-ChildItem -File -Filter $filter | Copy-Item -Destination $target -Container -Force
This solution uses 2 steps; there's probably a better option, but due to the peculiarities / bug in this cmdlet the above's a reliable option.