존재하지 않는 파일이 있습니까?

존재하지 않는 파일이 있습니까?

(빈 소스/싱크 파일 경로) 줄을 따라 /dev/null적어도 Linux에서는 유효한 파일을 가리키지 않는 경로가 있습니까? 이는 주로 제가 작성 중인 일부 스크립트를 테스트하기 위한 것이며 스크립트에 속하지 않는 파일이 존재하는 경우 이를 삭제하거나 이동하고 싶지는 않습니다.

답변1

대안으로, 스크립트가 임시 디렉토리를 생성한 다음 그 안에서 파일 이름을 찾는 것이 좋습니다. 이렇게 하면 파일이 존재하지 않는다고 100% 확신할 수 있으며 모든 권한을 갖고 직접 쉽게 정리할 수 있습니다. 그것은 다음과 같습니다:

dir=$(mktemp -d)
if [ -e "$dir"/somefile ]; then
    echo "Something is seriously wrong here, '$dir/somefile' exists!"
fi
rmdir "$dir"

어떤 언어로든 동등한 코드를 작성할 수 있으며 대부분의 (모두?) 고급 언어에는 임시 디렉토리 생성 및 삭제를 처리하는 전용 도구가 있습니다. 이는 존재해서는 안 되는 파일 이름을 추측하는 것보다 더 안전하고 깔끔한 접근 방법인 것 같습니다.

답변2

/dev/null/foo/dev/null디렉토리가 아니면 존재할 수 없습니다 .

POSIX 요구 사항/dev/null"빈 데이터 소스이자 무한한 데이터 싱크"가 됩니다. 이러한 특징을 지닌 디렉토리를 갖는 것이 완전히 불가능한지는 잘 모르겠습니다. 그래도 나는 /dev/null그것이 *nix의 디렉토리가 아니라고 가정하는 것이 안전하다고 생각합니다.

열려고 하면 (해당 파일이나 디렉터리 없음) 대신 (디렉토리 아님)을 /dev/null/foo받게 됩니다 . 이는 테스트 목적에 따라 허용될 수도 있고 허용되지 않을 수도 있습니다.ENOTDIRENOENT

답변3

암호화 핸드북에서 잎사귀를 꺼내면 충분히 큰 임의 문자열을 생성하면 적중 가능성이 미미할 정도로 사소한 확률로 특정 시스템에만 존재하게 됩니다.

예를 들어, 작업 파일이 있고 /dev/urandom그래야 한다고 가정하면 다음과 같이 f128비트 난수를 기반으로 유효한 파일 이름이 생성됩니다.

f=/$(head -c 16 /dev/urandom |base64 |tr / ,)

출력은 다음과 같습니다 /B90sYd,aNrcw7d7Itcb8fQ==. (선행 슬래시는 고정되어 있으며 의도적으로 절대 경로로 만들어졌습니다. 후행 슬래시 ==도 고정되어 있으며 Base64 패딩으로 인해 무시할 수 있습니다.)

1조/초의 속도로 임의의 파일 이름을 생성하는 시스템은 스크립트로 생성된 파일 이름을 생성하는 데 수조 년이 걸립니다. 충돌만으로는 충분하지 않으므로 생일 공격이 적용되지 않습니다. 이는 기본적으로 128비트 대칭 키를 무차별 암호 해독하는 것과 동일합니다.

예를 들면 다음을 참조하세요. AES-128 키를 무차별 대입하는 데 시간이 얼마나 걸리나요?

이것은 유효한 문자열이 필요하다는 점에 유의하세요 . 누군가가 이를 Base64로 인코딩할 때 문자열을 생성하는 /dev/urandom알려진 문자열(예: 3바이트)이 포함된 정적 파일로 대체하면 작동하지 않습니다 . 에드 컨텍스트. 또한, 예를 들어 시스템의 RNG를 초기화할 수 있는 실질적인 수단이 없는 임베디드 시스템은 문제에 직면할 수 있습니다. 이 경우에는 사용하지 마세요.\x86\x89\x9ehomechroot/dev/urandom이 경우 암호화 키를 생성하지 마세요..


대안으로 빈 문자열을 사용할 수 있습니다. 적어도 Linux에서는 파일 이름으로 사용하려고 하면 오류가 발생합니다.

$ cat ""
cat: '': No such file or directory
$ touch ""
touch: cannot touch '': No such file or directory

(그런데 오류( ENOENT)가 좀 흥미롭습니다. 이름이 유효하지 않다고 생각할 수도 있습니다.존재하지 않는다.)

이것을 변수에 넣으면 확장할 때 따옴표를 기억해야 합니다! 예를 들어 f=; cat $f표준 입력에서 읽으면 됩니다.

$ f=
$ cat "$f"
cat: '': No such file or directory
$ touch "$f"
touch: cannot touch '': No such file or directory

그러나 cd ""셸에서 이 작업을 수행하면 현재 디렉터리로만 변경됩니다.POSIX 라고저것"[주어진 경로]가 빈 문자열인 경우 결과는 지정되지 않습니다.". 내가 시도한 모든 쉘은 call 에서 현재 경로를 명시적으로 사용합니다 chdir(). 예를 들면 다음과 같습니다.

/tmp$ strace -etrace=chdir zsh -c 'cd ""'
chdir("/tmp")                           = 0
+++ exited with 0 +++
/tmp$

내 생각은 이전 (현재)을 기반으로합니다.삭제됨) 답변. 이것은 시스템에 따라 다를 수도 있고 아닐 수도 있습니다. Linux에서만 시도했습니다. 경고 사항.


[ -f ... ]또한 주석에서 언급했듯이, 어떤 오류가 발생하는지 신경 쓰지 않거나 쉘 이나 셸에서 알려주지 않는 것을 사용하는 경우 [ -e ... ]매우 긴 파일 이름을 만들 수 있습니다.

거의 모든 파일 시스템에서 단일 파일의 최대 길이는 255자 이하입니다(참조:파일 시스템 비교위키피디아에서). 전체 경로는 더 길 수 있지만 256바이트의 단일 파일 이름은 불가능하며 다음을 제공합니다 ENAMETOOLONG.

$ f=$(printf %256s x | tr ' ' x)
$ touch "$f"
touch: cannot touch 'xxx...xxx': File name too long

그러나 if [ -e "$f" ]; then ...내가 시도한 모든 쉘에는 오류가 없으며 테스트도 실패했습니다.

(이것POSIX 정의이것이 -e"false if"라고 말해보세요경로명해결할 수 없습니다"라는 메시지가 표시되지만 진단을 명시적으로 언급하지 않습니다. 따라서 일부 구현이 경우에 따라 잘못될 수 있는지 확실하지 않습니다. 이 경우에 해당한다면 알려주시기 바랍니다.)

(Wikipedia의 표에는 파일당 길이가 더 긴 두 개의 Linux 파일 시스템이 언급되어 있지만 현재 널리 사용되는지는 의심스럽고 Linux는 일반적으로 파일 시스템에 관계없이 255바이트 제한이 있다는 것도 알고 있습니다.)

답변4

테든훌륭한 답변이 이미 제공되었습니다.사용mktemp -d. 이 기사에서는 문제를 보다 기본적인 방식으로 살펴보고 설명합니다.일반적으로 이 명령이 가장 좋은 대답입니다.

아니요마디 없는결코 존재하지 않는 길. 하지만 테스트 스크립트에 대한 귀하의 문장에 따르면 다음과 같이 들립니다.바꾸다스크립트가 경로를 자체적으로 생성할 수 있는 한 경로도 마찬가지로 좋습니다.

이러한 경로를 생성하는 유일한 방법은 생성된 경로가 더 이상 존재하지 않을 때까지 경로 생성을 유지하는 것입니다. 불행하게도 이로 인해 다음과 같은 결과가 발생할 수 있습니다.경쟁 조건: 다른프로그램파일이 생성될 수 있음뒤쪽에존재하는지 확인하지만앞으로존재하지 않는 파일에 의존하는 작업을 수행합니다.

이러한 경쟁 상태를 피하는 가장 좋은 방법은 다른 프로그램이 피해야 하는 경로를 사용하는 것입니다. /tmp예를 들어 불행히도 /tmp세상은 종종 쓰기 가능하므로 이제 더 큰 문제가 있습니다.사용자파일이 생성될 수 있습니다.

당신이 정말로 원하는 것은 다른 프로그램이 피해야 하는 임시 디렉토리입니다그리고다른 사용자는 접근할 수 없습니다. 해당 디렉토리 아래의 모든 경로를 사용할 수 있도록 디렉토리가 비어 있으면 더 좋을 것입니다.

mktemp -d자체 경쟁 조건으로부터 자신을 보호하면서 이전 단락의 모든 기준을 충족하는 디렉터리를 만듭니다. 완료되면 rmdir다음 명령을 사용하여 디렉터리를 삭제할 수 있습니다.

dir="$(mktemp -d)"
# Use "$dir"/foo as a nonexistent path.
rmdir "$dir"

관련 정보