0

Is there any easy way to create a text file in only readme sub-folder I want to create a read-me.txt file with content example@gmail.com I don't want to open folder one by one there are thousands of folders in partition C:\management

│
├───employees
│    ├───1559ad36254x
│    │    ├───work
│    │    ├───logs
│    │    └───readme
│    └───ayu6734287as
│         ├───work
│         ├───logs
│         └───readme
├───acy7wr7grill
├───acsaagsdy345rchs
├───adarsyuewoli
├───adgw843brhe
├───ahbe67ts
├───…
└───…

Is there any command that can create a file in every readme sub directory I am trying with this command to find readme directory and then create a new file using echo command

cd C:\management & for /f %x in ('dir readme /a:d /s /b') do echo example@gmail.com>%x\read-me.txt

This command is working but taking too much time because first it will find all paths containing readme folder:

C:\management\employees\1559ad36254x\readme
C:\management\employees\ayu6734287as\readme
C:\management\acsaagsdy345rchs\random87as\readme
C:\management\zsaagsdy345rchs\fir87as\readme

After that it will create a new file in readme directory. Is there any Powershell or Cmd command that can find path then create file then find next path and create file?

Steven
  • 6,817
  • 1
  • 14
  • 14
Sadam
  • 107
  • 2
  • 9

2 Answers2

3

This is very easy to do with PowerShell:

Get-ChildItem 'c:\management' -Directory -Recurse -Filter 'readme' |
New-Item -ItemType File -Path {$_.FullName} -Name readme.txt -Value 'example@gmail.com'

The Get-ChildItem command will recursively get folders named readme. the result will be piped to the New-Item command where we'll use an expression to specify the path and create a file named "readme.txt" with content "example@gmail.com"

Note: the lack of an explicit loop, this could have been written like:

Get-ChildItem 'c:\temp' -Directory -Filter 'readme' -Recurse |
ForEach-Object{
    New-Item -ItemType File -Path $_.FullName -Name readme.txt -Value 'example@gmail.com'
}

However, New-Item allows an expression to be used for the -Path argument, allowing the first, more concise example.

Steven
  • 6,817
  • 1
  • 14
  • 14
  • 1
    Interesting is the expression support for `New-Item` parameter `-Path`. It looks like this is missing from the official documentation? – zett42 Apr 14 '21 at 13:09
  • 1
    @zett42 Yeah I've looked for that and haven't found it, but crazy as it seems there's some subset of cmdlets & parameters that will contextually accept `$_` with in a script block expression. Honestly, I struggled with it a bit, but it's a reason to look at fundamental QA on SO. I think MS plays fast & loose with the definition, it's somewhat explained in [About_Calculated_Properties](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_calculated_properties?view=powershell-7.1). But, still no mention of non-get *item cmdlets. – Steven Apr 14 '21 at 14:17
  • Finally found it. Support for scriptblock arguments is an implicit feature of parameters that accept pipeline input. This is explained at [about_Script_Blocks](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_script_blocks?view=powershell-7.1#using-delay-bind-script-blocks-with-parameters) and more in depth in [this answer](https://stackoverflow.com/a/52807680/7571258). – zett42 Apr 14 '21 at 17:51
  • Great sleuthing! At least I'm not crazy... Somehow I knew mklement0 would have the answer... It would probably still be nice to have some explanation in the cmdlet specific. – Steven Apr 14 '21 at 19:58
  • You may want to upvote this [GitHub request](https://github.com/PowerShell/PowerShell/issues/15241) I just created to make the feature more discoverable in the documentation. – zett42 Apr 15 '21 at 19:19
  • 1
    I just gave it the thumbs up. I'm Nashiooka on there. – Steven Apr 15 '21 at 20:54
2

Apply FOR /D (Conditionally perform a command on several Directories/Folders) rather than FOR /F:

Unlike other variants of the FOR command you must include a wildcard (either * or ?) in the 'folder_set' to get consistent results returned. In many cases you can work around this by adding a single character wildcard e.g. if you are looping through multiple folders to find the exact folder January you could instead specify Janu?ry.

cd C:\management & FOR /D /r %x IN (rea?me) DO @echo example@gmail.com> "%x\read-me.txt"

To exclude possible reaxme, realme or alike:

cd C:\management & FOR /D /r %x IN (rea?me) DO @if /I "%~nxx"=="readme" echo example@gmail.com> "%x\read-me.txt"

Here %~nxx evaluates to a name and extension only, see for /?.

JosefZ
  • 28,460
  • 5
  • 44
  • 83
  • 1
    This is probably one of the faster ways as well! cmd definitely has an edge on timeliness over Posh. – Abraham Zinala Apr 14 '21 at 14:22
  • this command is faster then ```for /f``` but can you tell me why it is faster than my ```for /f``` command – Sadam Apr 14 '21 at 15:05
  • 2
    @Sadam, `for /F` begins iterating upon `dir /S /B` is finished, while `for /D /R` begins iterating more or less immediately; at the end there will not be that much difference in speed. By the way, use `cd /D C:\…` rather than `cd C:\…`… – aschipfl Apr 14 '21 at 16:16
  • @aschipfl sorry i did not understand.. ```for /f``` start creating a new file in every directory after full completion of this command ```dir /S /B``` ??? – Sadam Apr 14 '21 at 18:31
  • 2
    @Sadam I can approve aschipfl's statement. `for /f` waits for full completion of a command because it (`dir readme /a:d /s /b` in your case) runs in a child `cmd` instance. And `cd /D C:\…` (or `pushd C:\…`) is a good idea as well. – JosefZ Apr 14 '21 at 19:06