2013-10-02 3 views
1

У меня есть папка из тысяч имен файлов.Манипуляция файлами и папками в Powershell

Все имена файлов относятся к идентификатору пользователя. Некоторые пользователи имеют несколько файлов в этой папке, поэтому он добавляет число в конец имени. И.Е. susy.txt, susy1.txt, susy2.txt, carl.txt, carl1.txt и т. д.

То, что я пытаюсь сделать, это создать определенную папку для каждого пользователя с несколькими файлами и переместить все связанных файлов в эту папку. Поэтому я замечаю, что есть несколько подозрительных документов. Поэтому я хочу создать папку с именем Susy и поместить в нее файлы susy.txt, susy1.txt и susy2.txt ... И так далее для всех файлов.

Возможно ли это сделать как пакетный файл, если это возможно, кто-то может указать мне в правильном направлении на это? У меня есть небольшой объем знаний в написании пакетных скриптов, и я хотел бы принять это как возможность узнать больше.

Благодаря

ответ

3

Это более простой и компактный способ:

Get-ChildItem | ?{$_.Name -match '(\D+)\d*\.txt'} | %{ 
    md $matches[1] -ea SilentlyContinue 
    Move-Item $_ $matches[1] 
} 

пуристом мог бы сказать, что это «лучшая практика» для Test-Path, прежде чем пытаться создать каталог, но я обычно предпочитаю более компактный код; если никакие другие решения не зависят от того, существует ли каталог, то быстрее попытаться создать ее каждый раз и проигнорировать ошибки.


Несколько пояснительных записок, в ответ на замечание OP в:

  • ?{ } представляет собой сокращенную Where-Object, который фильтрует на состоянии, то есть только те объекты, которые удовлетворяют заданному условию передаются по трубопроводу. Таким образом, в этом случае он принимает список текущего каталога и выбирает только объекты, свойства соответствует регулярному выражению.
  • После использования оператора -match, совпадения хранятся в переменной автоматического массива $ совпадений. $ matches [0] содержит всю согласованную часть строки, а индексы, начинающиеся с 1, содержат группы соответствия, пронумерованные из порядкового положения левой скобки, то есть $ matches [1] - это группа совпадений, начиная с первая левая скобка встречается, $ матчей [2] это совпадение группы, начиная со второго левой скобки и т.д.

    В этом случае есть только одна группа матч, и $ матчей [1] содержит часть строки, сопоставленная (\D+), то есть последовательность последовательных нецифровых символов до первой цифры или точки.

+0

Хорошо, это сработало Amazing и просто, как я этого хочу. Спасибо! Я, очевидно, не профессионал, но я это понимаю по большей части ... Я просто не знаю, что означает? {} Означает и $ matches [1]. В основном [1], я не понимаю. Еще раз спасибо! – Johnrad

+0

Еще раз спасибо! Идеальный смысл! – Johnrad

2

Вот мой быстрый и грязный просто сфабриковано решение. Он использует регулярное выражение для разделения имени пользователя из имени файла, то есть выражение разделит carl из carl1.txtcarl3.txtcarl22.txt. Затем он создает папки из этих имен, уникально. Поэтому он только пытается создать carl один раз, а не 57 раз. После этого он перемещает все carl и johnny и susy и т. Д. В новые папки.

Если вы новичок, не бойтесь, если это кажется немного пугающим. Особенно регулярные выражения. Есть почти наверняка способ сделать это без них, если они вас смущают, но регулярные выражения - один из тех инструментов, которые, когда вы узнаете это, вы знаете, насколько это хорошо для решения вещей.

[regex]$pattern_name = '^\w.+?(?=[\d\.])' 

# create folders for all the unique users 
get-Childitem -File -path 'c:\scripts' | foreach-Object {$pattern_name.match($_).value } | sort -unique | foreach-Object { mkdir $_ } 

# move files into those folders 
get-Childitem -File -path 'c:\scripts' | foreach-Object { 
    $user = $pattern_name.match($_).value 
    Move-Item -destination ".\$user" -Path $_.FullName 
    } 
+0

+1 - Обратите внимание, что это создаст каталог для пользователя, даже если у них есть только один файл, что не то, о чем попросил ОП. – dugas

+0

Согласовано. Хотя, вероятно, они хотели: P – EdgeVB

+0

Пара проблем с этим регулярным выражением ... не основные, но мне интересно, почему вы так написали. (1) Почему '.' после' \ w' в регулярном выражении? Хотя это не * вероятно *, что имя будет иметь только один символ, OP не указал не менее двух символов. Кроме того, почему вам требуется только первый символ, в частности, быть в классе \ w, а после этого соответствовать любому символу до первой цифры или периода? –

0

Один из способов сделать это. Что это такое:

  1. Содержит файлы в каталоге по имени пользователя.

  2. Если группа имеет более одного файла, она создает каталог для пользователя, а затем перемещает файлы пользователя в этот каталог.

(Обратите внимание, что я добавил -WhatIf вариант для всех команд, которые будут модифицируют данные - вам придется удалить их на самом деле изменить данные .)

# Make backup for safety 
cp -recurse .\userFiles .\userFilesBackup 

cd .\userFiles 

gci | ` 

select-object @{n='User';e={$_.BaseName -replace "^([a-z]+)[\d]*$", '$1'}}, Name | ` 

group-object User | ` 

? { $_.Count -gt 1 } | ` 

% { ` 

$userDirectory = $_.Name 
mkdir -WhatIf $userDirectory 

foreach ($f in $_.Group) 
{ mv -WhatIf $f.Name $userDirectory } 

} 
Смежные вопросы