Powershell — узнать, есть ли два файла с одинаковым именем

Я пытаюсь проверить ряд каталогов и подкаталогов, чтобы увидеть, есть ли в одной папке два или более файла с одинаковым именем. Я думаю, что моя проблема в том, как я пытаюсь проверить строку.

Для следующего тестового каталога:

  • |-- C:\Test\
    • |--C:\Test\YY\
      • |--C:\Test\YY\xx.log
      • |--C:\Test\YY\xx.txt
    • |-- C:\Test\ZZ\
    • |-- C:\Test\ZZ.log
    • |-- C:\Test\ZZ.txt

Мне нужен мой код, чтобы найти xx.log и ZZ.log. Я могу включить проверку против $_.PSisContainer (но я не думаю, что это необходимо).

ForEach ($item in (gci "C:\Test\*" -recurse)) {
    If ($item.extension -notmatch "txt" -AND $item.basename+".txt" -eq $True) {
        Write-Host $item.fullname
        } 
    }

$item.basename+".txt" предоставляет правильную строку, но я не могу использовать эту строку для проверки существования файла.

Может ли кто-нибудь помочь исправить мой код? Я хотел бы узнать, как обрабатывать объединенные строки, подобные этому, - я думаю, что этот трюк будет полезен в других областях.


person R_C_III    schedule 29.07.2014    source источник


Ответы (2)


Это не предназначено как ответ, а скорее как комментарий, но ТАК не позволяет мне добавлять комментарии прямо сейчас :(

R_C_III - Думаю, в исходном коде две ошибки.

Во-первых, он не создает полный путь к файлу (т. е. DirectoryName + BaseName + .TXT). Вместо объединения строк для этого Кит использовал возможность PowerShell выполнять подстановку значений внутри строк в двойных кавычках. например

$s = "there"
write-host "hello $s"

приводит к

hello there

Чтобы вставить свойства объекта в строку таким образом, необходимо использовать подвыражения, как объясняет Кит.

$file = get-item "c:\somefile.txt"
write-host "$($file.DirectoryName)\$($file.BaseName).NEW"

приводит к

c:\somefile.NEW

Во-вторых (согласно моему комментарию к ответу Кейта), исходный код не проверяет наличие версии файла «.txt». Второе предложение в операторе IF пытается приравнять измененное имя файла к $True ($item.basename+".txt" -eq $True). Это предложение всегда будет оцениваться как ложное.

Модификация Кейта добавляет CmdLet «Test-Path», который в данном случае проверяет наличие файла «.txt».

person andyb    schedule 30.07.2014
comment
Благодарю вас! Отличный ответ! Я сузил основную проблему: не могли бы вы объяснить следующий пример? $item.basename+".txt" создает System.String из ZZ.txt test-path $item.basename+".txt" не может быть найдена ошибка позиционного параметра, которая принимает аргумент '+.txt', и write-host $item.basename+".txt" создает ZZ +.txt $($item.basename+".txt") создает System.String из ZZ.txt, а write-host показывает ZZ. txt Внешне они должны быть одинаковыми, но write-host показывает по-разному. Я думаю, что это моя проблема в ОП. Все строки не созданы равными? @andyb @кейт-хилл - person R_C_III; 01.08.2014
comment
Сильно подозреваю, что это как-то связано с режимами синтаксического анализа PowerShell. Я отсылаю вас к одной из замечательных статей Кита (rkeithhill.wordpress.com/2007/11/24/), а также "get-help about_parsing" - person andyb; 04.08.2014

Попробуй это:

gci C:\Test -recurse -file | Where {$_.extension -ne ".txt" -AND (Test-Path "$($_.DirectoryName)\$($_.BaseName).txt")}

Вам не нужен начальный оператор Foreach, поскольку команды PowerShell позволяют использовать выходные данные непосредственно в начале конвейера. Затем вы фильтруете объекты конвейера с помощью команды Where.

person Keith Hill    schedule 29.07.2014
comment
Работает отлично! Спасибо! Не могли бы вы объяснить, как работает $($_.DirectoryName)\$($_.BaseName).txt? Как $() делает то, чего не делал мой $_.Basename+.txt? - person R_C_III; 30.07.2014
comment
Чтобы оценить выражение, такое как ссылка на свойство, внутри строки вам нужно использовать подвыражение, т. е. $(). - person Keith Hill; 30.07.2014
comment
R_C_III. Мне кажется, что ваше исходное выражение пытается приравнять строку ($item.basename+.txt) к логическому значению ($True). Кит добавил CmdLet Test-Path, который проверяет существование файла. - person andyb; 30.07.2014