![Linux에서 () 및 공백과 같은 특수 문자를 사용하여 파일 이름을 지속적으로 만드는 방법은 무엇입니까? [폐쇄]](https://linux55.com/image/117100/Linux%EC%97%90%EC%84%9C%20()%20%EB%B0%8F%20%EA%B3%B5%EB%B0%B1%EA%B3%BC%20%EA%B0%99%EC%9D%80%20%ED%8A%B9%EC%88%98%20%EB%AC%B8%EC%9E%90%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20%ED%8C%8C%EC%9D%BC%20%EC%9D%B4%EB%A6%84%EC%9D%84%20%EC%A7%80%EC%86%8D%EC%A0%81%EC%9C%BC%EB%A1%9C%20%EB%A7%8C%EB%93%9C%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F%20%5B%ED%8F%90%EC%87%84%5D.png)
을 사용하여 많은 파일을 만들려고 합니다 C
. 난 끝냈어 mkdir -p directory && touch directory/filename
. 내 루프가 이름에 특수 문자가 포함된 파일에 도달하면 오류가 발생합니다.
syntax error :" unexpected "("
도와주세요?
답변1
귀하의 문제 system()
는 system()
. 이는 또한 결과 쉘이 자체 구문을 사용하여 전체 명령을 평가하므로 쉘이 특별히 처리하는 문자를 이스케이프해야 함을 의미합니다.
C에서 파일과 디렉터리를 생성하는 보다 강력하고 오류가 덜 발생하는 방법은 이 작업을 위해 제공되는 실제 C 함수, 즉 mkdir()
및 open()
/ 를 사용하는 것입니다 creat()
.
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
int
main(void)
{
char dir[] = "some(directory)with*special[characters]";
char file[] = "some(file)with*the[same]characters";
int fd;
if (mkdir(dir, 0755) == -1)
err(EXIT_FAILURE, "creating directory failed");
if ((fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
err(EXIT_FAILURE, "creating file failed");
close(fd);
/* ... */
return 0;
}
답변2
다음과 같이 파일 경로를 따옴표로 묶습니다.
touch "directory/file"
답변3
파일 이름을 "인용"해야 합니다.
touch "directory/file with whitespace (and special characters)"
인용문과 특수문자에 대해서는 bash 매뉴얼을 읽어보세요.
답변4
system()
매개변수가 포함된 쉘 명령을 호출하기 위해 inside를 사용하는 경우 C
이러한 매개변수를 인용하지 않도록 환경을 사용하여 매개변수를 전달하는 것이 가장 좋습니다.
파일 경로(문자 포함)는 다음 위치에 저장됩니다 file_path
.
if (setenv("FILE", file_path, 1) < 0) {
perror("setenv");
exit(1);
}
system("mkdir -p -- \"$(dirname -- \"$FILE\")\" && touch -- \"$FILE\"");
이렇게 하면 (내부에서 호출된) 고정 문자열을 전달할 수 sh -c
있으며 쉘 코드가 정확하다면(위의 인용문 참고) system()
임의 코드 주입 취약점에 대해 걱정할 필요가 없습니다.--
sh
(위의 내용 에는 모든 후행 줄 바꿈이 제거되는 일반적인 명령 대체 문제가 있으므로 file_path
유사한 상황에서는 실패 합니다 foo/bar\n/file
. 이에 대해 작업할지 여부는 귀하가 결정하도록 하겠습니다).
쉘 코드의 파일 이름을 전달하려는 system()
경우아니요하다:
sprintf(cmd, "mkdir -p -- \"%s\" && touch -- \"%s\"", dir_path, file_path);
이는 여전히 명령 주입 취약점이기 때문입니다(예: 파일 이름은 $(reboot)
또는 와 같습니다 ";reboot;:"
. 큰따옴표 대신 작은따옴표를 사용하는 경우에도 마찬가지입니다.
다음을 수행해야 합니다.
sprintf(cmd, "mkdir -p -- %s && touch -- %s",
shquote(dir_path), shquote(file_path));
각 문자를 작은따옴표 로 바꾸고 결과를 묶는 shquote()
함수(구현은 연습으로 남음)는 어디에 있습니까? 따라서 예를 들어 return for (참조된 파일은 최대 4 * 길이 + 2가 될 수 있으므로 버퍼에 공간을 할당할 때 이를 고려해야 함 ).'
'\''
'foo'\''bar'
foo'bar
cmd
이것이 가장 안전한 참조 방법입니다. 큰따옴표나 백슬래시를 사용하는 인용 방법은 외부 문자 집합을 사용하는 일부 로케일에서 문제가 되어 잠재적으로 임의 코드 삽입 취약점을 초래할 수 있습니다.