File.Move가 작동하지 않음-파일이 이미 있습니다.


86

폴더가 있습니다.

c : \ test

이 코드를 시도하고 있습니다.

File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test");

예외가 발생합니다.

존재하는 파일입니다

출력 디렉토리가 확실히 존재하고 입력 파일이 있습니다.


2
입력 파일이 이미 출력 디렉토리에있는 경우 파일이 이미 존재하므로 예외를 설명합니다. 원본 파일을 새 파일로 덮어 쓸 것임을 표시해야합니다 .
Cody Gray

9
오류가 정확히 무엇이 잘못되었는지 알려주는 것 같습니다.
Josh

@Josh 아니요. Windows가 POSIX가 아닌 파일 시스템 동작을 수행하여 간단한 휴대용 트랜잭션 파일 업데이트 패턴 / 루틴을 알아내는 것이 불가능한 것 같습니다.
binki

@binki POSIX는 관련이 없으며 ( 원자 적 작업 을 참조하고 있습니까?) NTFS 롤백 및 원본 파일 내용 다시 가져 오기에서와 같이 실제 트랜잭션 작업을 지원합니다. 다른 사람들이 대답했듯이 Win32 교체와 함께 이동을 허용합니다. 기능을 제공하지 않는 .NET의 File.Move입니다. AlphaFS
Panagiotis Kanavos

2
@binki 어떤 경우에도 동작은 포럼 토론에서 말하는 것과 상관없이 다른 파일 시스템 에서 잘 정의 됩니다 . File.Move가 Ex 또는 Transacted 메서드를 호출하지 않는 이유는 여전히 메모리 카드에서 사용되기 때문에 무시할 수없는 FAT 원 자성 이 아니고 동일하게 작동 하지 않기 때문 입니다. 이름 변경은 메타 데이터 작업이 아니며 실제 데이터 이동이 필요합니다. 그리고 트랜잭션 및 기록 중 복사는 잊어 버리십시오. 좋은 결정 imho
Panagiotis Kanavos

답변:


62

폴더가 아닌 다른 파일로 이동해야하며 이름을 바꾸는 데 사용할 수도 있습니다.

움직임:

File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test\SomeFile.txt");

이름 변경 :

File.Move(@"c:\test\SomeFile.txt", @"c:\test\SomeFile2.txt");

예제에서 "파일이 이미 존재합니다"라고 표시되는 이유 는 확장자가없는 C:\test\Test파일을 만들려고 Test하지만 같은 이름의 폴더가 이미 존재하므로 그렇게 할 수 없기 때문입니다.


139

필요한 것은 :

if (!File.Exists(@"c:\test\Test\SomeFile.txt")) {
    File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test\SomeFile.txt");
}

또는

if (File.Exists(@"c:\test\Test\SomeFile.txt")) {
    File.Delete(@"c:\test\Test\SomeFile.txt");
}
File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test\SomeFile.txt");

이것은 다음 중 하나입니다.

  • 파일이 대상 위치에 존재하지 않는 경우 파일을 성공적으로 이동하거나;
  • 파일이 대상 위치에 존재하는 경우 삭제 한 다음 파일을 이동하십시오.

편집 : 가장 찬성표를 받았음에도 불구하고 내 대답을 명확히해야합니다! File.Move의 두 번째 매개 변수는해야한다 대상 파일 - 하지 폴더. 두 번째 매개 변수를 대상 파일 이름이 아닌 대상 폴더로 지정 합니다. 이는 File.Move에 필요한 것입니다. 따라서 두 번째 매개 변수는 c:\test\Test\SomeFile.txt.


그가 확인 중이고 파일이 존재하지 않기 때문에 파일이 없는지 확인할 필요가 없습니다. 예외는 파일 이름을 다른 폴더로 이동하려고 할 때 대상 폴더에 추가하지 않기 때문에 발생합니다.
하디 Eskandari

3
앱이 다중 스레드 (또는 파일에서 작동하는 다른 프로세스가있는 경우) 인 경우 "if (Exists) Delete"코드를 사용해도 동일한 예외가 발생할 수 있습니다. 여전히 다른 스레드 / 프로세스가 삭제 후 파일을 다시 넣을 수있는 시간 공간이 있으므로 이동을 수행 한 다음 어쨌든 예외가 발생합니다. 명심할 가치가 있습니다. :-)
bytedev

11
이 답변은 기존 파일을 덮어 쓰려고 시도한 후 Google을 사용하는 대부분의 사람들에게 여전히 유효합니다. 이 곤경에 처한 대부분의 사람들은 OP와 같은 구문 / 유형 문제가 없습니다.
WEFX 2013

1
@ v.oddou 흥미롭게도 파일이 존재하지 않으면 File.Delete가 실제로 올바르게 작동하고 아무것도하지 않습니다. 대신 경로의 디렉토리가 존재하지 않으면 DirectoryNotFoundException이 발생합니다.
Brandon Barkley

2
@JirkaHanika if (File.Exists)를 while (File.Exists)로 변경할 수 있습니다.
Brandon Barkley

39

개인적으로이 방법을 선호합니다. 이렇게하면 대상의 파일을 덮어 쓰고 원본 파일을 제거하며 복사가 실패 할 때 원본 파일이 제거되지 않도록합니다.

string source = @"c:\test\SomeFile.txt";
string destination = @"c:\test\test\SomeFile.txt";

try
{
    File.Copy(source, destination, true);
    File.Delete(source);
}
catch
{
    //some error handling
}

4
작은 파일 (원자 적 이동에 대한 요구 사항 없음)에는 문제가 없지만 큰 파일이나 중복으로 끝나지 않는지 확인해야하는 경우에는 문제가됩니다.
River Satya

왜 선호합니까 File.Copy , File.Delete이상 File.Move?
John Pietrar

6
File.Move에는 덮어 쓰기 옵션이 없습니다.
Mitchell

1
사용 사례에 따라 문제가 발생할 수 있습니다. "Move"는 파일 시스템 감시자의 실제 이벤트입니다. 파일 시스템 이벤트에 대한 목록은 이동 이벤트 대신 삭제 및 생성 이벤트를 가져옵니다. 이렇게하면 기본 파일 시스템 ID도 변경됩니다.
Andrew Rondeau 2018 년

1
대용량 파일의 경우 성능이 훨씬 떨어지지 않습니까? 원본과 대상이 동일한 물리적 볼륨에있는 경우 이유없이 두 번째 복사본을 만든 다음 원본을 삭제하는 반면 File.Move ()는 원본과 대상이 같은 볼륨에있는 경우 추가 작업을 수행하지 않습니다.
Brad Westness

18

P / Invoke를 수행하여 ( )에 대해 11MoveFileEx()전달할 수 있습니다.flagsMOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
static extern bool MoveFileEx(string existingFileName, string newFileName, int flags);

또는 전화를 걸 수 있습니다.

Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(existingFileName, newFileName, true);

Microsoft.VisualBasic을 참조로 추가 한 후.


앱이 Windows에서만 실행되는 경우 완전히 괜찮습니다. 이것은 som P / Invoke를 시도하려는 대부분의 사람들에게 좋은 대답 일 것입니다.
Todd

9

파일이 실제로 존재하고 교체하려면 아래 코드를 사용하십시오.

string file = "c:\test\SomeFile.txt"
string moveTo = "c:\test\test\SomeFile.txt"

if (File.Exists(moveTo))
{
    File.Delete(moveTo);
}

File.Move(file, moveTo);

5

1) .Net Core 3.0 이상에서 C #을 사용하면 이제 세 번째 부울 매개 변수가 있습니다.

참조 https://docs.microsoft.com/en-us/dotnet/api/system.io.file.move?view=netcore-3.1를

In .NET Core 3.0 and later versions, you can call Move(String, String, Boolean) setting the parameter overwrite to true, which will replace the file if it exists.

2) 다른 모든 버전의 .Net의 경우 https://stackoverflow.com/a/42224803/887092 가 가장 좋은 답변입니다. 덮어 쓰기로 복사 한 다음 소스 파일을 삭제합니다. 원자 적 연산이되기 때문에 더 좋습니다. (나는 이것으로 MS Docs를 업데이트하려고 시도했습니다)


4

File.Move대한 문서에 따르면 "존재하는 경우 덮어 쓰기"매개 변수가 없습니다. 대상 폴더 를 지정하려고했지만 전체 파일 사양을 제공해야합니다.

문서를 다시 읽으면 ( "새 파일 이름을 지정하는 옵션 제공"), 대상 폴더 사양에 백 슬래시를 추가하는 것이 작동 할 수 있다고 생각 합니다.


그리고 문서 에는 같은 이름의 파일을 해당 디렉토리로 이동하여 파일을 바꾸려고 시도하면 IOException이 발생합니다. 이를 위해 Move(String, String, Boolean)대신 전화하십시오 . 하지만 그게 실수 인 것 같나요?
Kevin Scharnhorst

@KevinScharnhorst이 답변은 2011 년이었습니다. 이제 문서에는 Move with Overwrite에 대한 .Net Core 3.0 지원이 포함됩니다.
Todd


1

새 위치에서 이미 존재하는 파일을 삭제할 수있는 옵션이 없지만 원래 위치에서 이동 및 삭제해야하는 경우이 이름 변경 트릭이 작동 할 수 있습니다.

string newFileLocation = @"c:\test\Test\SomeFile.txt";

while (File.Exists(newFileLocation)) {
    newFileLocation = newFileLocation.Split('.')[0] + "_copy." + newFileLocation.Split('.')[1];
}
File.Move(@"c:\test\SomeFile.txt", newFileLocation);

이것은 유일한 '.' 파일 이름에서 확장자 앞에 있습니다. 확장자 앞에 두 개로 파일을 분할하고 "_copy"를 첨부합니다. 사이. 이렇게하면 파일을 이동할 수 있지만 파일이 이미 존재하거나 사본의 사본이 이미 존재하거나 사본의 사본이 존재하는 경우 사본을 작성합니다 ...;)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.