![병렬 처리를 위한 xargs의 와일드카드 변수](https://linux55.com/image/172223/%EB%B3%91%EB%A0%AC%20%EC%B2%98%EB%A6%AC%EB%A5%BC%20%EC%9C%84%ED%95%9C%20xargs%EC%9D%98%20%EC%99%80%EC%9D%BC%EB%93%9C%EC%B9%B4%EB%93%9C%20%EB%B3%80%EC%88%98.png)
질문
이 함수가 bash 호출 내에 있을 때 VAR
함수(예: wilcard)에서 wilcard와 함께 입력 변수를 사용하는 데 ls
문제가 있습니다 .*
xargs
이 xargs
함수는 파일 이름 접두사 목록의 각 구성원에 대해 반복됩니다 InfilePrefix_List.csv
.
입력 변수는 VAR
다음 형식의 문자열입니다 VAR="dir/sub_dir/SharedPrefix_InfilePrefix"
.
ls ${VAR}*
VAR
로 인해 디렉터리를 찾을 수 없다는 오류가 발생합니다 *
.
해결책
마지막으로 입력 목록은 .csv 파일로 저장되고 xargs는 각 목록 항목 뒤에 추가된 "\r"을 읽습니다. .csv 파일을 수정한 후 기능이 원활하게 실행되었습니다. 여기에서 동일한 질문을 확인하세요.https://www.unix.com/unix-for-dummies-questions-and-answers/124289-xargs-appending-r.html
건배
단순화된 예제와 병렬 컴퓨팅
실제로 제가 사용하는 함수는 ls
가 아니라: 입니다. cdo ensmean infiles*.nc outfile.nc
이는 여러 복제된 기후 데이터 파일에서 앙상블을 의미하게 됩니다.
그러나 이 기사에서는 사용된 예제 ls infiles*.nc
가 좋습니다. 옵션에서 제공하는 병렬 컴퓨팅 성능을 xargs
활용해야 하기 때문에 for 루프 대안을 사용하지 않습니다 .xargs --max-procs 44
Bash 스크립트 예
#!/bin/bash
more /dir/subdir/File_Prefix_List.csv | xargs -I {} bash -c "
echo 'arg is '{};
VAR=\$(echo /dir/subdir/SharedPrefix_{});
echo 'var is '\$VAR;
ls \${VAR}*.nc;
exit 1;"
노트
2행 - {}는 특정 InfilePrefix
문자열을 나타냅니다.
3,5행 - VAR이 올바른지 확인하기 위해 에코됩니다.
6행 - 예제 함수는 이름에 포함된 모든 파일을 ls
나열하는 것입니다.SharedPrefix_InfilePrefix
디버깅편집
요청에 따라 다음은 이러한 변경 사항이 적용된 샘플 bash 스크립트의 출력입니다.head -n 1 ...<my specific directories>... xargs -I {} bash -vxc " ...
내 특정 사례의 경우 예제와 내가 실행한 코드의 차이점은 다음과 같습니다. (1) /dir/subdir = /nobackup/b9035080/NCdata_RealsPalau
. (이십 /SharedPrefix_ = /Reals_Palau_tos_Oday_
삼 ) {} = ACCESS-CM2_historical
.
출력: 1행과 2행: xargs 인수( {} = ACCESS-CM2_historical
) 및 디렉터리 변수( VAR = /nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
)가 정확합니다. 3행: 와일드카드를 읽는 동안 오류가 발생했습니다.
섹션 1의 출력 끝 부분에는 관련성이 있다고 생각되는 오류 메시지가 표시됩니다.
;cho 'arg is 'ACCESS-CM2_historical
' echo 'arg is ACCESS-CM2_historical
arg is ACCESS-CM2_historical
);R=$(echo /nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
++ echo $'/nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical\r'
+ VAR=$'/nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical\r'
echo 'var is '$VAR;
' echo 'var is /nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
var is /nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
ls ${VAR}*.nc;
*.nc''/nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
*.nc: No such file or directory35080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
exit 1;
+ exit 1
파트 2 - 전체 출력, 일부는 이해가 안 됩니다. 모두 관련된 것인지 확실하지 않습니다. 죄송합니다. 저는 Unix를 처음 접합니다!
module () { eval $($LMOD_CMD bash "$@");
[ $? = 0 ] && eval $(${LMOD_SETTARG_CMD:-:} -s sh)
}
ml () { eval $($LMOD_DIR/ml_cmd "$@")
}
# -*- shell-script -*-
if [[ ${-/x} != $- ]]; then
echo "Start of Lmod init/bash script to define the module command"
fi
+ [[ hvBc != hvxBc ]]
+ echo 'Start of Lmod init/bash script to define the module command'
Start of Lmod init/bash script to define the module command
LMOD_PKG=/usr/share/lmod/lmod
+ LMOD_PKG=/usr/share/lmod/lmod
LMOD_DIR=/usr/share/lmod/lmod/libexec
+ LMOD_DIR=/usr/share/lmod/lmod/libexec
LMOD_CMD=/usr/share/lmod/lmod/libexec/lmod
+ LMOD_CMD=/usr/share/lmod/lmod/libexec/lmod
MODULESHOME=/usr/share/lmod/lmod
+ MODULESHOME=/usr/share/lmod/lmod
export LMOD_PKG
+ export LMOD_PKG
export LMOD_CMD
+ export LMOD_CMD
export LMOD_DIR
+ export LMOD_DIR
export MODULESHOME
+ export MODULESHOME
########################################################################
# Define the module command: The first line runs the "lmod" command
# to generate text:
# export PATH="..."
# then the "eval" converts the text into changes in the current shell.
#
# The second command is the settarg command. Normally LMOD_SETTARG_CMD
# is undefined or is ":". Either way the eval does nothing. When the
# settarg module is loaded, it defines LMOD_SETTARG_CMD. The settarg
# command knows how to read the ModuleTable that Lmod maintains and
# generates a series of env. vars that describe the current state of
# loaded modules. So if one is on a x86_64 linux computer with gcc/4.7.2
# and openmpi/1.6.3 loaded, then settarg will assign:
#
# TARG=_x86_64_gcc-4.7.2_openmpi-1.6.3
# TARG_COMPILER=gcc-4.7.2
# TARG_COMPILER_FAMILY=gcc
# TARG_MACH=x86_64
# TARG_MPI=openmpi-1.6.3
# TARG_MPI_FAMILY=openmpi
# TARG_SUMMARY=x86_64_gcc-4.7.2_openmpi-1.6.3
# TARG_TITLE_BAR=gcc-4.7.2 O-1.6.3
# TARG_TITLE_BAR_PAREN=(gcc-4.7.2 O-1.6.3)
#
# unloading openmpi/1.6.3 automatically changes these vars to be:
#
# TARG=_x86_64_gcc-4.6.3
# TARG_COMPILER=gcc-4.6.3
# TARG_COMPILER_FAMILY=gcc
# TARG_MACH=x86_64
# TARG_SUMMARY=x86_64_gcc-4.6.3
# TARG_TITLE_BAR=gcc-4.6.3
# TARG_TITLE_BAR_PAREN=(gcc-4.6.3)
#
# See Lmod web site for more details.
module()
{
eval $($LMOD_CMD bash "$@")
[ $? = 0 ] && eval $(${LMOD_SETTARG_CMD:-:} -s sh)
}
LMOD_VERSION="6.5.1"
+ LMOD_VERSION=6.5.1
export LMOD_VERSION
+ export LMOD_VERSION
if [ "${LMOD_SETTARG_CMD:-:}" != ":" ]; then
settarg () {
eval $(${LMOD_SETTARG_CMD:-:} -s sh "$@" )
}
fi
+ '[' : '!=' : ']'
########################################################################
# ml is a shorthand tool for people who can't type moduel, err, module
# It is also a combination command:
# ml -> module list
# ml gcc -> module load gcc
# ml -gcc intel -> module unload gcc; module load intel
# It does much more do: "ml --help" for more information.
unalias ml 2> /dev/null || true
+ unalias ml
+ true
ml()
{
eval $($LMOD_DIR/ml_cmd "$@")
}
export_module=$(echo "YES" | /usr/bin/tr '[:upper:]' '[:lower:]')
++ echo YES
++ /usr/bin/tr '[:upper:]' '[:lower:]'
+ export_module=yes
if [ -n "${BASH_VERSION:-}" -a "$export_module" != no ]; then
export -f module
export -f ml
fi
+ '[' -n '4.2.46(2)-release' -a yes '!=' no ']'
+ export -f module
+ export -f ml
unset export_module
+ unset export_module
########################################################################
# clearMT removes the ModuleTable from your environment. It is rarely
# needed but it useful sometimes.
clearMT()
{
eval $($LMOD_DIR/clearMT_cmd bash)
}
########################################################################
# The following make the action of the settarg available to the titlebar
# for both xterm's and screen but only for interactive shells.
if [ -n "${PS1:-}" ]; then
if [ -n "${LMOD_FULL_SETTARG_SUPPORT:-}" -a "$LMOD_FULL_SETTARG_SUPPORT" != no ]; then
xSetTitleLmod()
{
builtin echo -n -e "\033]2;$1\007";
}
SET_TITLE_BAR=:
case "$TERM" in
xterm*)
SET_TITLE_BAR=xSetTitleLmod
;;
esac
SHOST=${SHOST-${HOSTNAME%%.*}}
precmd()
{
eval $(${LMOD_SETTARG_CMD:-:} -s bash)
${SET_TITLE_BAR:-:} "${TARG_TITLE_BAR_PAREN}${USER}@${SHOST}:${PWD/#$HOME/~}"
${USER_PROMPT_CMD:-:}
}
# define the PROMPT_COMMAND to be precmd iff it isn't defined already.
: ${PROMPT_COMMAND:=precmd}
fi
fi
+ '[' -n '' ']'
########################################################################
# Make tab completions available to bash users.
if [ ${BASH_VERSINFO:-0} -ge 3 ] && [ -r /usr/share/lmod/lmod/init/lmod_bash_completions ] && [ -n "${PS1:-}" ]; then
. /usr/share/lmod/lmod/init/lmod_bash_completions
fi
+ '[' 4 -ge 3 ']'
+ '[' -r /usr/share/lmod/lmod/init/lmod_bash_completions ']'
+ '[' -n '' ']'
if [[ ${-/x} != $- ]]; then
echo "End of Lmod init/bash script to define the module command"
fi
+ [[ hvBc != hvxBc ]]
+ echo 'End of Lmod init/bash script to define the module command'
End of Lmod init/bash script to define the module command
;cho 'arg is 'ACCESS-CM2_historical
' echo 'arg is ACCESS-CM2_historical
arg is ACCESS-CM2_historical
);R=$(echo /nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
++ echo $'/nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical\r'
+ VAR=$'/nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical\r'
echo 'var is '$VAR;
' echo 'var is /nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
var is /nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
ls ${VAR}*.nc;
*.nc''/nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
*.nc: No such file or directory35080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical
exit 1;
+ exit 1
답변1
bash -vx
출력 라인에서 볼 수 있듯이
+ VAR=$'/nobackup/b9035080/NCdata_RealsPalau/Reals_Palau_tos_Oday_ACCESS-CM2_historical\r'
\r
입력 줄 끝에 캐리지 리턴(CR, )이 있습니다. 물론 Unix 개행 문자(LF, \n
)가 제거되지 않고 문자열의 일부가 되지 않는 한 더 이상 파일 시스템 경로와 일치하지 않습니다.