34

Find an unused drive letter

Your task is to write the shortest code to find one of the unused drive letters (excluding a,b and c). PowerShell’s default aliases are allowed. You have one week.  Answers should be posted as a comment to this brain teaser. That’s it.


The winner gets a copy of  the “VMware vSphere PowerCLI Reference” from Sybex!

We’ll post clues over the next couple days, stay tuned.

Good Luck!

 

[UPDATE] 1/23/2012

We have a winner: P!
Your code was 36 characters long:

for($j=67;gdr($d=[char]++$j)2>0){}$d

This is the breakdown of our solution (47 characters):

ls function:[d-z]: -n|?{!(test-path $_)}|random

We took a different approach (though more lengthy) to get a list of available by listing the default A-Z functions and using the Name switch to get the names only.
We then tested if a drive with the incoming drive letter name was available, if so, it was written back to the pipeline.
Finally, we used the Get-Random cmdlet to choose for us an available letter. As you can see we called Get-Random by its verb only. You may suspect that ‘random’ is an alias for that command but it isn’t. We used a known trick to shorten Get-Random – when PowerShell cannot resolve a command it tries to resolve it again by prepending the Get verb.

We hope you had fun and that you enjoyed participating and was able to learn a thing or two. See you in the next brain teaser.
We also would like to thanks our sponsors, Sybex, for giving away the book for the Winner.

 

Filed in: Brainteasers Tags: , , ,

2 Pingbacks/Trackbacks

34 Responses to "Find an unused drive letter"

  1. jrich says:

    68..90|%{$l=gwmi win32_volume|%{$_.driveletter -replace “:” }}{if($l -notcontains [char]$_){[char]$_}}
    -jrich
    http://jrich523.wordpress.com

  2. P. says:

    68..90 | % { $d = [char]$_; if (!(gdr $d -erroraction SilentlyContinue)) { $d; break; }}

  3. Emin says:

    68..90|%{if(!(gdr ([char]$_) -EA 0)){[char]$_;break}}

  4. Emin says:

    68..90|%{$d=[char]$_;if(!(gdr $d -EA 0)){$d;break}}

  5. P. says:

    68..90|%{[char]$_}|%{if(!(gdr $_ -EA 0)){$_;break}}

  6. P. says:

    [char[]](68..90)|%{if(!(gdr $_ -EA 0)){$_;break}}

    49 characters!

  7. jrich says:

    33!
    [char[]](68..90)|?{!(gdr $_ -ea 0)}

  8. Simone says:

    [char[]](68..90)|%{if(!(gdr $_)){break}}

  9. P. says:

    if failure is an option, it can be done in 35

    [char[]](68..90)|%{$x=gdr $_ -ea 1}

  10. jrich says:

    ([char[]](68..90)|?{!(gdr $_ -ea 0)})[0]

    38 with error checking

  11. jrich says:

    ([char[]](68..90)|?{!(gdr $_ -ea 0)})[0]

    38 with error checking

  12. I can’t improve on JRich’s 38 chars to meet the original spec.
    But I can over come Joe’s objection in 44.

    for($j=67;gdr([char]$j)-ea 0){$j++};[char]$j

  13. Jeff Lubar says:

    seems to work just fine for me… good job!

    PS C:UsersJeffrey> [char[]](68..90)|?{!(gdr $_ -ea 0)}FGHIJKLMNOPQRSTUVWXYZPS C:UsersJeffrey>

  14. Makovec says:

    Get-PSDrive is not showing hidden drives (for example the one for AppV client), so had to use WMI. Running XP, so can’t use Win32_Volume:

    ([char[]](68..90)|?{@(gwmi win32_LogicalDisk|%{($_.deviceid)[0]}) -notcontains $_})[0]

    BTW – I like the idea of short contests (not necessary with prizes). But please – not on Friday when I am busy in the office :))

  15. ShayLevy says:

    Hey all

    Thanks for participating, you rock! A few comments and clarifications:

    1. Your answer should not generate an error.

    2. You need to output just one drive letter (with or without a colon).

    3. @jrich, the following is 40 char long, not 38 (and if you’re out of letters it may fail):  
    ([char[]](68..90)|?{!(gdr $_ -ea 0)})[0]

    4. @makovec, initially we didn’t think about AppV drives so we can’t change the requirements now :)

    5. Our one-liner answer is 47 characters  long.

    6. Keep’em coming!

  16. P. says:

    Going further with James’s idea

    for($j=67;gdr([char]++$j)-ea 0){}[char]$j

  17. Emin says:

    Other ideas:

    ([char[]](68..90)|?{@(mountvol|Select-string “[A-Z]:\”|%{$_.toString().Trim()[0]}) -notcontains $_})[0]
    ([char[]](68..90)|?{@([system.io.DriveInfo]::GetDrives()|%{($_.Name)[0]}) -notcontains $_})[0]
    ([char[]](68..90)|?{@([io.Directory]::GetLogicalDrives()|%{($_)[0]}) -notcontains $_})[0]
    ([char[]](68..90)|?{@([io.DriveInfo]::GetDrives()|%{($_.Name)[0]}) -notcontains $_})[0]
    ([char[]](68..90)|?{@(wmic logicaldisk get name|%{($_)[0]}) -notcontains $_})[0]
    net use ((((net use * \DCsysvol) -split “`n”)[0]).substring(6,1)+”:”) /d
    # based on: http://powershell.com/cs/blogs/tips/archive/2009/10/21/find-next-available-drive-letter.aspx
    (68..90|%{“$([char]$_):”}|?{([IO.DriveInfo]$_).DriveType -eq ‘noRootdirectory’})[0]
    [char]([int][char](gdr -PS FileSystem)[-1].Name+1)

  18. P. says:

    for($j=67;gdr($d=[char]++$j)-ea 0){}$d

  19. Bluraydisk says:

    Great exercise, it cost me whole morning, but learn a lot.
    Thanks, Claudio

  20. Elimelek says:

    # 37 chars:
    for($j=67;gdr($d=[char]++$j)2>$e){}$d

    # pipeline approach, 38 chars:
    ([char[]](68..90)|?{!(gdr $_)})[0]2>$e

  21. P. says:

    36

    for($j=67;gdr($d=[char]++$j)2>0){}$d

  22. Elimelek says:

    # 32 chars, implicit cast through the left hand rule:
    [char](1+[char](gdr ?)[-1].name)

  23. Elimelek says:

    Is the contest still open for one last trick?

    # 24 chars:
    [char](1+”$(gdr ?)”[-1])

  24. IMO gdr can lead to wrong results… prefer WMI/ .NET solutions. I just created ‘E’ drive that points to my registry and most of scripts here show F as first available letter. ;) Solutions that assume that first available = next in alphabet after last used fail miserably, because I have virtual cd ‘Z’ ;)
    My 2 attempts (I admit, I was using Emim’s ideas a lot:
    ([char[]](68..90)|?{!((gwmi cim_logicaldisk)-match”=.$_”)})[0]
    ([char[]](68..90)|?{!([io.driveinfo]::GetDrives()-match$_)})[0]

    This code is awful to read (kill me for using -match in such a way, I deserve it ;)).
    And most likely has other flaws that in turn I missed. :>

    • Elimelek says:

      Unless otherwise indicated, brainteasers – and their solutions – should be set in a common and leveled field, i.e. a non-profile powershell session. Having said that, I don’t think many systems would have ‘Z’ logical drive by default

© 9496 PowerShell Magazine. All rights reserved. XHTML / CSS Valid.
Proudly designed by Theme Junkie.
%d bloggers like this: