추가된 특정 파일 이름/확장자에 따라 출력 파일의 이름을 지정하고 아카이브하기 위해 현재 디렉터리의 모든 파일을 추가하려고 합니다.
기본적으로 .exe 확장자로 추가되는 파일이 있는 경우 ID는 .exe가 하나만 있고 적어도 하나라는 가정 하에 아카이브 이름이 해당 파일과 동일하기를 바랍니다.
Foo.exe -> Foo.7z
지금까지 내가 가지고 있는 스크립트는 다음과 같습니다. 7z a archive.7z *.* -x!*.sh
답변1
set -- *.exe
*.exe
일치하는 항목이 없는 한 일치하는 파일 이름을 위치 매개변수로 저장합니다 . 일치하는 항목이 없는 경우 결과는 셸에 따라 다릅니다(의 시작 부분 참조).이 답변); POSIX 셸에서는 *.exe
첫 번째이자 유일한 위치 매개변수로 리터럴 문자열을 얻습니다.
정확히 일치하는 항목이 하나 있다고 확신하는 경우 아무것도 테스트할 필요가 없습니다. 확실하지 않은 경우:
- ( )
$#
로 확장되는지 확인하고 ,1
[ "$#" -eq 1 ]
- 의심되는 파일이 존재하는지 확인하세요(
[ -e "$1"]
).
그러면 당신이 찾고 있는 이름은 에 있습니다 $1
. 번역하려면 Foo.exe
다음 Foo.7z
을 수행해야 합니다.제거하다exe
그리고 7z
( ${1%exe}7z
)를 추가하세요.
스니펫은 다음과 같습니다.
(
set -- *.exe
# here validate $# and/or $1 if necessary
7z a "${1%exe}7z" …
)
저는 서브쉘을 사용했기 때문에 set
메인 쉘의 위치 매개변수에는 영향을 주지 않습니다.인용이 중요하다.
노트:
- 솔루션에서는 일치 항목이 디렉터리가 되도록 허용합니다.모든 디렉토리도 파일입니다.
- "모든 파일 추가"라고 쓴 다음
*.* -x!*.sh
. 나는 제외가 "모든 파일"과 모순된다고 말하면서 문제를 제기하지 않을 것입니다. 하지만 문제가 있습니다.-x!*.sh
따옴표로 묶어야 하므로 쉘이 확장되지 않습니다*
. 일부 쉘은!
큰따옴표로도 확장되므로 문자열은 작은따옴표로 묶어야 합니다 .*.*
Windows에서는 "모든 파일"을 의미할 수 있습니다(적어도몇 가지 도구를 사용하여), 그러나 Linux 셸에서는 점이 점과 정확히 일치합니다.*
파일 이름 생성 패턴이 "모든 파일"에 더 가깝기 때문에여전히 "모든 파일"은 아닙니다.
- 솔루션은 다음과 같은 경향이 있습니다.TOCTOU. 아마도 디렉토리의 내용이 "무작위로" 변경되지 않으며 솔루션이 작동할 것입니다. 디렉토리가 정적이 아닌 경우 임시 이름을 가진 아카이브를 생성하고 해당 내용을 나열하고 구문 분석하여
.exe
아카이브에 무엇이 있는지 알아보고 마지막으로 그에 따라 아카이브 이름을 바꿔야 할 수 있습니다. - Linux의 파일 이름은 일반적으로 대소문자를 구분합니다. 파일 이름을 다루는 도구도 대소문자를 구분합니다. 일반적으로
set -- *.exe
감지하지 못합니다FOO.EXE
. 일부 쉘에서는 이 동작을 조정할 수 있습니다(예:shopt -s nocaseglob
Bash에서 조사). 그런 다음 이름 번역 중 이나 다른 변형을${1%[eE][xX][eE]}7z
적절하게 처리하는 데 사용할 수 있습니다 .EXE
Exe