DirectoryInfo.MoveTo — исходный и целевой пути должны иметь одинаковые корни. Move не будет работать между томами.

Я пытаюсь понять, что здесь происходит. У меня есть процедура, которая просматривает все каталоги в каталоге и удаляет любые нечисловые значения из первой части имени каталога. По какой-то причине, когда он выполняет MoveTo, я получаю сообщение «Исходный и конечный пути должны иметь одинаковые корни. Перемещение не будет работать между томами». Но я указываю только новое имя в качестве параметра. Таким образом, каталог может быть «007A Raby», а новое имя, переданное в MoveTo, будет «007 Raby». У кого-нибудь есть мысли, что я делаю не так?

    private void RenameSubs(string directory)
    {
        try
        {
            if (Directory.Exists(directory))
            {
                var parentDI = new DirectoryInfo(directory);

                foreach (var di in parentDI.GetDirectories())
                {
                    var spaceLocation = di.Name.IndexOf(' ');
                    var changed = false;

                    if (spaceLocation > 0)
                    {
                        var oldName = di.Name;
                        var subPartA = di.Name.Substring(0, spaceLocation);
                        var subPartB = di.Name.Substring(spaceLocation, di.Name.Length - spaceLocation);

                        for (int i = subPartA.Length - 1; i > 0; i--)
                        {
                            if (subPartA[i] < '0' || subPartA[i] > '9')
                            {
                                subPartA = subPartA.Substring(0, i);
                                changed = true;
                            }
                            else
                            {
                                break;
                            }
                        }

                        if (changed)
                        {
                            if (!Directory.Exists(Path.Combine(directory, subPartA + subPartB)))
                            {
                                var newName = subPartA + subPartB;
                                di.MoveTo(newName);
                                txtOutput.Text += "Renamed " + oldName + " to " + di.Name + "\r\n";
                            }
                            else
                            {
                                txtOutput.Text += "Error " + oldName + " already exists " + "\r\n";
                            }
                        }
                        else
                        {
                            txtOutput.Text += "Ignored " + di.Name + "\r\n";
                        }
                    }
                }
            }   
        }
        catch (System.Exception excpt)
        {
            txtOutput.Text += "Error " + excpt.Message + "\r\n";
            Console.WriteLine(excpt.Message);
        }
    }

person dblwizard    schedule 24.10.2014    source источник
comment
Вы можете опубликовать несколько строк кода, чтобы воспроизвести ошибку (Исходный и конечный пути должны иметь одинаковые корни. Перемещение не будет работать между томами.) вместо того, чтобы заставлять нас читать все несвязанные коды. Как насчет публикации SSCCE   -  person L.B    schedule 25.10.2014
comment
Воспользуйтесь отладчиком и посмотрите на значение newName. Бьюсь об заклад, это не то, что вы ожидали. Также в более общем примечании: используйте класс System.IO.Path для управления именами каталогов и файлов (вместо прямых операций со строками); и, ради всего святого, не сравнивайте логические выражения с литералами... Я имею в виду, что это законно и работает, но менее читабельно, чем просто писать if (!Directory.Exists(...))   -  person Peter Duniho    schedule 25.10.2014
comment
Питер, я проверил отладчик, и новое имя — это именно то, что я ожидал: 007 Raby, а свойство di.Name — 007A Raby. Я не буду спорить о читабельности Exists == false, но как это сравнивать с литералом?   -  person dblwizard    schedule 25.10.2014
comment
LB, я думал, что это был небольшой SSCCE, поскольку я думал, что это уместно. Я предполагаю, что это как-то связано с коллекцией, возвращаемой из GetDirectories, потому что я прогнал небольшой образец, который просто использует один di для выполнения того же самого и не смог воспроизвести проблему. Поэтому я счел необходимым включить все, что я сделал.   -  person dblwizard    schedule 25.10.2014
comment
Таким образом, при еще одном тестировании ошибка связана с путем к приложению и расположением каталога. Приведенный выше код работает, пока я указываю на тот же диск, на котором работает приложение. Но как только каталог указывает на другой диск, он терпит неудачу.   -  person dblwizard    schedule 27.10.2014


Ответы (1)


Хорошо, после проб и ошибок я понял, как это исправить. когда «относительный путь» передается в DirectoryInfo.MoveTo, он использует не родительский путь, а путь приложения. Поэтому, когда я сказал, что это сработало, потому что оно было на том же диске, что и приложение, я пропустил, что оно переименовало папки в папку приложения. Чтобы исправить это, мне нужно было передать абсолютный путь к методу MoveTo. Вот изменение кода, необходимое внутри блока кода «если (изменено)», чтобы это работало:

    var newName = Path.Combine(directory, subPartA + subPartB);

    if (!Directory.Exists(newName))
    {
        di.MoveTo(newName);
        txtOutput.Text += "Renamed " + oldName + " to " + di.Name + "\r\n";
    }
    else
    {
        txtOutput.Text += "Error " + oldName + " already exists " + "\r\n";
    }

Надеюсь, это поможет кому-то еще.

person dblwizard    schedule 27.10.2014