여러 가지 응용 프로그램이 열려 있습니다. 달리기wmctrl출력을 파이프로 연결앗다음과 같이 창 ID("고정" 창 제외)를 나열합니다.
$ wmctrl -l | awk ' !/-1/ { print $1 } '
0x00a00018
0x04800005
0x04e00005
0x04400003
0x05000003
0x0540002b
0x05a00012
0x05800002
0x05c00003
$
이 출력을 다음으로 보낼 수 있습니다.wmctrl이 창을 모두 닫으려면 다음을 수행하세요.
저장해야 할 내용이 없는 창과 응답이 필요 없는 창은 묻지도 않고 닫히지만
저장되지 않은 콘텐츠가 있는 편집자 창이나 프로세스를 실행 중인 터미널의 창은 "정상적으로" 닫힙니다. 각 응용 프로그램은 변경 사항을 저장하거나 변경 사항을 취소하거나 아직 실행 중인 프로세스에 대해 알릴 수 있는 창을 표시합니다.
적절한 바로가기에 할당된 다음 스크립트가 작동합니다.
#!/bin/bash
list=$(wmctrl -l | awk ' !/-1/ { print $1 } ')
for i in ${list[@]}
do
wmctrl -i -a $i
wmctrl -i -c $i
done
나는 (나에게) 더 간단한 방법 for i in $list
도 효과가 있다는 것을 알았습니다.
둘 중 하나를 선호하는 이유가 있나요?
"끈끈한"과 "우아하게"는 의 용어입니다 man wmctrl
.
답변1
귀하의 스크립트 $list
에서는 ${list[@]}
.
후자는 배열 구문이지만 스크립트에서는 일반 변수입니다.
출력 항목 에 공백이 없으므로 wmctl
배열이 필요하지 않으며 사용하는 것이 $list
완벽합니다.
그 경우~였다배열은 $list
배열의 첫 번째 항목(=> item1
) 일 뿐이며 ${list[@]}
모든 항목으로 확장됩니다(=> item1 item2 item3
).
하지만 실제로 당신이 원했던 것은~였다배열은 "${list[@]}"
(따옴표 포함)로 확장되므로 "item1" "item2" "item3"
공백으로 인해 질식하지 않습니다.
(읽다)
답변2
루프 는 명령 출력을 처리하는 데 루프 while
보다 더 적합한 경우가 많으며 for
, 이를 통해 라인을 목록에 저장하는 대신 직접 처리할 수 있습니다.또는정렬.
이 경우 명령을 완전히 피할 수 있습니다 awk
.
wmctrl -l | while read -r id dt stuff; do
case $dt in
-1) continue
;;
*) echo wmctrl -i -a "$id"
echo wmctrl -i -c "$id"
;;
esac
done
echo
올바른 일을 하고 있다고 생각되면 s를 제거하세요 .
의견에서 언급했듯이 xargs
또 다른 옵션입니다. 그러나 각각에 대해 두 가지 이상의 작업을 수행하려는 경우 까다로워집니다 arg
.
답변3
원래 제목에 대한 답변
원래 제목에서는 "어떤 유형의 for 루프가 더 나은지"를 물었습니다.
나 자신에게는 가장 좋은 방법은 가장 빠른 방법이다. 이를 확인하려면 time
스크립트나 함수 앞에 명령을 추가하세요. 몇 가지 예:
$ time du -s
real 0m0.002s
user 0m0.003s
sys 0m0.000s
$ time ls
real 0m0.004s
user 0m0.000s
sys 0m0.004s
하지만 테스트 사이에 캐시된 버퍼를 플러시하는 것이 중요합니다.
두 루프의 속도가 거의 같으면 가독성이 가장 좋은 루프를 선택하겠습니다.
이 질문의 범위는 대부분의 시간이 사용자 입력을 기다리는 데 소비되고 대부분의 사람들에게 최대 10개의 창만 열려 있기 때문에 속도와 관련이 없게 만드는 것입니다.
질문 본문에 대한 답변
다른 답변은 스크립트 다시 작성에 중점을 두므로 2센트 가치도 제공하겠습니다.
라인:
list=$(wmctrl -l | awk ' !/-1/ { print $1 } ')
- 의도가 배열인 경우 형식이 잘못되었습니다.
list
일반적이며 설명적이지 않음
그래서 나는 다음을 사용할 것입니다 :
Windows=( $(wmctrl -l | awk ' !/-1/ { print $1 } ') )
- ()의 외부 세트는 bash/shell 내부의 모든 것이 공백으로 구분된 배열 요소임을 알려줍니다.
- Windows는 우리가 말하는 것이므로 설명적인 배열 이름입니다.
- Windows는 복수형이므로 명명 규칙을 사용하면 배열인지 식별하는 데 도움이 됩니다.
라인:
wmctrl -i -a $i
-i
으로-a
결합할 수 있습니다-ia
.$i
대신에 사용하겠습니다$Window
.
더 짧고 읽기 쉬운 스크립트를 작성하는 방법에는 두 가지가 있습니다. 먼저 배열을 사용합니다.
#!/bin/bash
Windows=( $(wmctrl -l | awk ' !/-1/ { print $1 } ' ) )
for Window in "${Windows[@]}" ; do wmctrl -ia $Window -c $Window ; done
배열이 없는 두 번째:
#!/bin/bash
Windows=$(wmctrl -l | awk ' !/-1/ { print $1 } ' )
for Window in $Windows ; do wmctrl -ia $Window -c $Window ; done
배열 방식을 선호하는 이유는 배열 방식에 대해 더 자세히 알아보고 최대한 활용하고 싶기 때문입니다. 그러나 선택은 귀하의 것입니다.
답변4
어레이 없이도 관리할 수 있습니다. 환경IFS줄 바꿈을 사용하면 라인을 반복할 수 있으므로 루프 자체에 영향을 주지 않고 루프 내부에서 IFS를 for
수행할 수 있습니다 .unset
#!/bin/bash
IFS=$'\n'
for i in $(wmctrl -l); do
unset IFS
set -- $i
(($2 > -1)) && wmctrl -i -a $1 -c $1
done
(재설정위치 매개변수라인을 필드로 분할하는 깔끔한 방법입니다.)
배열을 사용해야 하는 경우 사용할 수 있습니다.맵파일콜백 함수를 활용하여 루프와 유사한 것을 만듭니다. 소규모 반복 세트의 경우 더 간단한 함수 호출을 사용하는 것이 이점이 될 수 있습니다.
mapfile -c 1 -C 'f(){ set -- $@; (($3 >= 0)) && wmctrl -i -a $2 -c $2; }; f' -t < <(wmctrl -l)
(긴 버전):
#!/bin/bash
f(){
set -- $@
if (($3 > -1)); then
wmctrl -i -a $2 -c $2
fi
}
mapfile -c 1 -C f -t < <(wmctrl -l)