cp 대신 임시 파일로 파일을 교환하시겠습니까? [복사]

cp 대신 임시 파일로 파일을 교환하시겠습니까? [복사]

두 변수를 교환해야 하는 유명한 입문 프로그래밍 연습이 있습니다. 확실한 해결책은 세 번째 임시 변수를 사용하는 것입니다. 그러나 언어에 튜플과 같은 것이 있으면 인수를 역순으로 반환하는 매우 간단한 도우미 함수를 작성할 수 있습니다.

def swap(a: Int, b: Int): (Int, Int) = (b, a)
val (two, one) = swap(1, 2) // => (2, 1)

Linux에서의 파일 작업에서도 이것이 가능한지 궁금합니다. 예를 들어, 상황에 따라 바꾸고 싶은 구성이 있는 경우 두 개의 파일 이름을 가져와 해당 내용을 바꿀 수 있는 명령이 있습니까?
예를 들어, a.txt 파일의 내용이 "Hello"이고 b.txt의 내용이 "World"라고 가정합니다. 여기서 호출한 것을 호출한 후 swapa.txt에 "World"를 포함하고 b.txt에 "Hello"를 포함하고 싶습니다.

이 문제는 스왑 파티션이 모든 검색 결과를 지배했기 때문에 처음 생각했던 것보다 조사하기가 더 어려웠습니다.

답변1

커널 수준에서 이 작업을 수행하는 Linux 관련 시스템 호출이 있습니다.

관련 시스템 호출은 다음과 같습니다.renameat2()renameat()이는 이 문제를 해결하기 위해 추가 특정 플래그와 함께 사용할 수 있는 Linux 특정 확장입니다 . Linux 3.15에 추가되었으며 glibc 지원은 glibc 2.28에 추가되었습니다.

RENAME_EXCHANGE

원자 교환오래된 길그리고새로운 길. 두 경로 이름이 모두 존재해야 하지만 유형이 다를 수 있습니다. 예를 들어 하나는 비어 있지 않은 디렉토리이고 다른 하나는 기호 링크일 수 있습니다.

이 기능을 지원할 수 있는 파일 시스템에 대한 추가 제한이 있을 수 있습니다. 이것자식 검색2014년 이후 추가된 다양한 파일 시스템에 대한 지원 소개: ext4, 퓨즈, f2fs, shmem/tmpfs, xfs, gfs2, overlayfs, btrfs, ubifs, affs...

이 시스템 호출을 사용하기 위한 올바른 명령이 없는 경우 다음은 모든 기호가 "수동으로"(이 아키텍처 = 316 등) 원자적으로 해결되는 매우 아키텍처별(amd64/x86_64) Python의 예입니다. SYS_renameat2C에서 시스템 호출이 수행하는 작업을 보여주는 및 이름의 스왑 파일:abstrace

$ echo Hello > a.txt; echo World > b.txt
$ cat a.txt
Hello
$ cat b.txt
World
$ strace -e trace=renameat2 python3 -c 'import ctypes; libc = ctypes.CDLL(None); libc.syscall(316, -100, b"a.txt", -100, b"b.txt", 2);'
renameat2(AT_FDCWD, "a.txt", AT_FDCWD, "b.txt", RENAME_EXCHANGE) = 0
+++ exited with 0 +++
$ cat a.txt
World
$ cat b.txt
Hello

물론적절한 도서관회의단순화하다이 Python 예제.

답변2

그런 건 없는 것 같아요기준시스템 호출.그러나 Linux에는 하나가 있습니다.

전용 시스템 호출이 있든 없든 중요합니다. rename(a, tmp); rename(b, a); rename(tmp, b);모든 시스템에서 이 작업을 수행할 수는 있지만 원자적이지는 않기 때문입니다. 동시에 실행 중인 다른 프로세스에서 a이름을 바꾼 후 해당 프로세스를 열려고 하면 "파일을 찾을 수 없음" 오류가 나타날 수 있습니다. 먼저 교체하더라도 rename()항상 존재 link()하는지 확인하십시오 . 다른 프로세스에서 동일한 파일을 열고 가져올 수 a있습니다 .ab

다행스럽게도 두 개의 파일을 교환할 필요가 있는 경우는 많지 않습니다(또한 두 개의 변수를 교환하는 것이 일반적인 요구 사항인지 확실하지 않습니다). 대신, 리더가 부분적, 혼합 또는 손실된 데이터를 얻을 수 있는 지점을 남기지 않고 단일 파일 이름 뒤에 오는 내용을 바꾸는 것이 더 일반적입니다. 이 작업 rename()link()또는 을 통해 쉽게 수행할 수 있습니다 symlink().

한 구성 집합에서 다른 구성 집합으로 변경하는 예의 경우 활성 구성에 대한 기호 링크를 만든 다음 자동으로 링크를 바꿀 수 있습니다.

예를 들어 다음과 같은 경우

$ ls -l
total 8
-rw-r--r-- 1 ilkkachu ilkkachu  6 Oct 17 21:07 conf1
-rw-r--r-- 1 ilkkachu ilkkachu 13 Oct 17 21:07 conf2
lrwxrwxrwx 1 ilkkachu ilkkachu  5 Oct 17 21:07 current -> conf1

그러면 ln -sf conf2 current자동으로 다음으로 변경됩니다.

$ ls -l
total 8
-rw-r--r-- 1 ilkkachu ilkkachu  6 Oct 17 21:07 conf1
-rw-r--r-- 1 ilkkachu ilkkachu 13 Oct 17 21:07 conf2
lrwxrwxrwx 1 ilkkachu ilkkachu  5 Oct 17 21:07 current -> conf2

conf1마찬가지로 및를 동일한 파일에 대한 하드 링크로 사용 current하고 링크를 로 바꿀 수 있습니다 ln -f conf2 current.

답변3

피하고 싶은 것 같군요파일 내용 사본파일을 사용하여 이를 달성하는 두 가지 방법을 생각할 수 있습니다.

  1. mv내용을 복사하지 않고 임시 파일을 통해 파일 이름을 바꾸는 데 사용됩니다 .

  2. 포인터와 유사한 심볼릭 링크를 사용하고 교체하는 대신 필요한 구성을 명시적으로 설정하십시오. 예를 들어

    
    $ls
    a.txt b.txt Define_setcfg.bash
    $cata.txt
    안녕하세요
    $catb.txt
    세계
    $cat 정의_setcfg.bash
    함수 setcfg() {
    echo Set 구성을 $1 # $1이 유효한 cfg 파일 이름으로 설정되었는지 확인해야 합니다.
    ln -sf $1actual.cfg # Actual.cfg라는 이름의 $1 심볼릭 링크를 생성합니다.
    }   
    
    $ source ./define_setcfg.bash # 현재 bash에서 함수 정의
    $ setcfg b.txt # setcfg 함수 사용
    구성을 b.txt로 설정
    $ ls -l # 지금 가지고 있는 것이 무엇인지 확인
    총 12개
    lrwxrwxrwx 1 사용자 이름 사용자 이름 5 10월 17일 18:33 Actual.cfg -> b.txt
    -rw-rw-r-- 1 사용자 이름 사용자 이름 6 10월 17일 18:08 a.txt
    -rw-rw-r-- 1 사용자 이름 사용자 이름 6 10월 17일 18:08 b.txt
    -rw-rw-r-- 1 사용자 이름 사용자 이름 161 10월 17일 18:25 Define_setcfg.bash
    $ setcfg a.txt # 매개변수 1로 a.txt를 제공하는 함수를 사용합니다.
    구성을 a.txt로 설정
    $ ls -l # 지금 가지고 있는 것이 무엇인지 확인
    총 12개
    lrwxrwxrwx 1 사용자 이름 사용자 이름 5 10월 17일 18:34 Actual.cfg -> a.txt
    -rw-rw-r-- 1 사용자 이름 사용자 이름 6 10월 17일 18:08 a.txt
    -rw-rw-r-- 1 사용자 이름 사용자 이름 6 10월 17일 18:08 b.txt
    -rw-rw-r-- 1 사용자 이름 사용자 이름 161 10월 17일 18:25 Define_setcfg.bash
    $   

답변4

이러한 명령은 작성하기 쉬우므로 숫자가 존재하는지 의심됩니다. 그런데 왜?

당신이 정말로 해결해야 할 문제는 무엇인가? 대부분의 경우 더 좋은 방법이 있습니다.

특정 이름을 가진 파일을 읽는 프로그램이 있고 두 가지 버전이 필요한 경우 일반적으로 제가 하는 일은 파일 시스템에 가용성을 나타내는 이름이 있는 두 가지 버전을 두고 이름이 있는 기호 링크를 사용하여 그 중 하나를 가리키는 것입니다. 프로그램 이름입니다. 실제 사용. 그런 다음 (을 사용하여) 심볼릭 링크를 업데이트하여 ln -sf둘 사이를 변경합니다.

관련 정보