아래와 같이 많은 하위 폴더가 있는 디렉터리가 있습니다(FA와 T1 콘텐츠가 쌍을 이루고 ..._L, ..._R 콘텐츠가 있다는 것을 기억하세요). 여기서 문자(a, b, c 등)로 명명된 폴더 수는 크게 다를 수 있습니다.
.
├── FA
│ ├── CN
│ │ ├── CN_L
│ │ │ ├── GE_FSPGR
│ │ │ │ ├── a
│ │ │ │ └── b
│ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ ├── c
│ │ │ │ └── d
│ │ │ └── SIEMENS_MPRAGE
│ │ │ ├── e
│ │ │ ├── f
│ │ │ ├── g
│ │ │ └── h
│ │ └── CN_R
│ │ ├── GE_FSPGR
│ │ │ ├── a
│ │ │ └── b
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── c
│ │ │ └── d
│ │ └── SIEMENS_MPRAGE
│ │ ├── e
│ │ ├── f
│ │ ├── g
│ │ └── h
│ └── Dementia
│ ├── Dementia_L
│ │ ├── GE_FSPGR
│ │ │ ├── i
│ │ │ └── j
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── k
│ │ │ └── l
│ │ └── SIEMENS_MPRAGE
│ │ ├── m
│ │ ├── n
│ │ ├── o
│ │ └── p
│ └── Dementia_R
│ ├── GE_FSPGR
│ │ ├── i
│ │ └── j
│ ├── PHILIPS_MPRAGE
│ │ ├── k
│ │ └── l
│ └── SIEMENS_MPRAGE
│ ├── m
│ ├── n
│ ├── o
│ └── p
└── T1
├── CN
│ ├── CN_L
│ │ ├── GE_FSPGR
│ │ │ ├── a
│ │ │ └── b
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── c
│ │ │ └── d
│ │ └── SIEMENS_MPRAGE
│ │ ├── e
│ │ ├── f
│ │ ├── g
│ │ └── h
│ └── CN_R
│ ├── GE_FSPGR
│ │ ├── a
│ │ └── b
│ ├── PHILIPS_MPRAGE
│ │ ├── c
│ │ └── d
│ └── SIEMENS_MPRAGE
│ ├── e
│ ├── f
│ ├── g
│ └── h
└── Dementia
├── Dementia_L
│ ├── GE_FSPGR
│ │ ├── i
│ │ └── j
│ ├── PHILIPS_MPRAGE
│ │ ├── k
│ │ └── l
│ └── SIEMENS_MPRAGE
│ ├── m
│ ├── n
│ ├── o
│ └── p
└── Dementia_R
├── GE_FSPGR
│ ├── i
│ └── j
├── PHILIPS_MPRAGE
│ ├── k
│ └── l
└── SIEMENS_MPRAGE
├── m
├── n
├── o
└── p
이 디렉터리를 백분율을 기준으로 테스트, 학습 및 검증으로 분할하고 싶습니다. 즉, 하위 폴더(a, b, c, d 등도 폴더임)의 60%, 20% 및 20%를 가져와 복사합니다. 동일한 상위 폴더와 동일한 페어링 구조를 유지하면서 해당 컬렉션(학습, 테스트 또는 검증)에 연결합니다. 제가 분명히 밝혔는지 모르겠습니다.
출력은 다음과 같습니다:
.
├── test
│ ├── FA
│ │ ├── CN
│ │ │ ├── CN_L
│ │ │ │ ├── GE_FSPGR
│ │ │ │ │ ├── a
│ │ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ │ ├── c
│ │ │ │ └── SIEMENS_MPRAGE
│ │ │ │ ├── e
│ │ │ │ ├── f
│ │ │ └── CN_R
│ │ │ ├── GE_FSPGR
│ │ │ │ ├── a
│ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ ├── c
│ │ │ └── SIEMENS_MPRAGE
│ │ │ ├── e
│ │ │ ├── f
│ │ └── Dementia
│ │ ├── Dementia_L
│ │ │ ├── GE_FSPGR
│ │ │ │ ├── i
│ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ ├── k
│ │ │ └── SIEMENS_MPRAGE
│ │ │ ├── m
│ │ │ ├── n
│ │ └── Dementia_R
│ │ ├── GE_FSPGR
│ │ │ ├── i
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── k
│ │ └── SIEMENS_MPRAGE
│ │ ├── m
│ │ ├── n
│ └── T1
│ ├── CN
│ │ ├── CN_L
│ │ │ ├── GE_FSPGR
│ │ │ │ ├── a
│ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ ├── c
│ │ │ └── SIEMENS_MPRAGE
│ │ │ ├── e
│ │ │ ├── f
│ │ └── CN_R
│ │ ├── GE_FSPGR
│ │ │ ├── a
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── c
│ │ └── SIEMENS_MPRAGE
│ │ ├── e
│ │ ├── f
│ └── Dementia
│ ├── Dementia_L
│ │ ├── GE_FSPGR
│ │ │ ├── i
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── k
│ │ └── SIEMENS_MPRAGE
│ │ ├── m
│ │ ├── n
│ └── Dementia_R
│ ├── GE_FSPGR
│ │ ├── i
│ ├── PHILIPS_MPRAGE
│ │ ├── k
│ └── SIEMENS_MPRAGE
│ ├── m
│ ├── n
├── train
│ ├── FA
│ │ ├── CN
│ │ │ ├── CN_L
│ │ │ │ ├── GE_FSPGR
│ │ │ │ │ ├── b
│ │ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ │ ├── d
│ │ │ │ └── SIEMENS_MPRAGE
│ │ │ │ ├── g
│ │ │ │ ├── h
│ │ │ └── CN_R
│ │ │ ├── GE_FSPGR
│ │ │ │ ├── b
│ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ ├── d
│ │ │ └── SIEMENS_MPRAGE
│ │ │ ├── g
│ │ │ ├── h
│ │ └── Dementia
│ │ ├── Dementia_L
│ │ │ ├── GE_FSPGR
│ │ │ │ ├── j
│ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ ├── l
│ │ │ └── SIEMENS_MPRAGE
│ │ │ ├── o
│ │ │ ├── p
│ │ └── Dementia_R
│ │ ├── GE_FSPGR
│ │ │ ├── j
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── l
│ │ └── SIEMENS_MPRAGE
│ │ ├── o
│ │ ├── p
│ └── T1
│ ├── CN
│ │ ├── CN_L
│ │ │ ├── GE_FSPGR
│ │ │ │ ├── b
│ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ ├── d
│ │ │ └── SIEMENS_MPRAGE
│ │ │ ├── g
│ │ │ ├── h
│ │ └── CN_R
│ │ ├── GE_FSPGR
│ │ │ ├── b
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── d
│ │ └── SIEMENS_MPRAGE
│ │ ├── g
│ │ ├── h
│ └── Dementia
│ ├── Dementia_L
│ │ ├── GE_FSPGR
│ │ │ ├── j
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── l
│ │ └── SIEMENS_MPRAGE
│ │ ├── o
│ │ ├── p
│ └── Dementia_R
│ ├── GE_FSPGR
│ │ ├── j
│ ├── PHILIPS_MPRAGE
│ │ ├── l
│ └── SIEMENS_MPRAGE
│ ├── o
│ ├── p
└── validation
├── FA
│ ├── CN
│ │ ├── CN_L
│ │ │ ├── GE_FSPGR
│ │ │ │ ├── aa
│ │ │ ├── PHILIPS_MPRAGE
│ │ │ │ ├── bb
│ │ │ └── SIEMENS_MPRAGE
│ │ │ ├── cc
│ │ │ ├── dd
│ │ └── CN_R
│ │ ├── GE_FSPGR
│ │ │ ├── aa
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── bb
│ │ └── SIEMENS_MPRAGE
│ │ ├── cc
│ │ ├── dd
│ └── Dementia
│ ├── Dementia_L
│ │ ├── GE_FSPGR
│ │ │ ├── ee
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── ff
│ │ └── SIEMENS_MPRAGE
│ │ ├── gg
│ │ ├── hh
│ └── Dementia_R
│ ├── GE_FSPGR
│ │ ├── ee
│ ├── PHILIPS_MPRAGE
│ │ ├── ff
│ └── SIEMENS_MPRAGE
│ ├── gg
│ ├── hh
└── T1
├── CN
│ ├── CN_L
│ │ ├── GE_FSPGR
│ │ │ ├── aa
│ │ ├── PHILIPS_MPRAGE
│ │ │ ├── bb
│ │ └── SIEMENS_MPRAGE
│ │ ├── cc
│ │ ├── dd
│ └── CN_R
│ ├── GE_FSPGR
│ │ ├── aa
│ ├── PHILIPS_MPRAGE
│ │ ├── bb
│ └── SIEMENS_MPRAGE
│ ├── cc
│ ├── dd
└── Dementia
├── Dementia_L
│ ├── GE_FSPGR
│ │ ├── ee
│ ├── PHILIPS_MPRAGE
│ │ ├── ff
│ └── SIEMENS_MPRAGE
│ ├── gg
│ ├── hh
└── Dementia_R
├── GE_FSPGR
│ ├── ee
├── PHILIPS_MPRAGE
│ ├── ff
└── SIEMENS_MPRAGE
├── gg
├── hh
저는 정말 무엇을 해야 할지 모르겠습니다. 저를 도와주시면 감사하겠습니다.
나는 이 게시물을 읽었습니다.하위 폴더를 통해 수천 개의 파일 배포, 하지만 내 문제에는 적합하지 않은 것 같아요.
감사해요
답변1
이것주택 검사-clean Bash 프로그램은 귀하의 요구에 적합할 수 있습니다:
#! /bin/bash -p
#### Utility functions
function quit
{
local -r msg=${1-unknown error}
printf '%s: ERROR: %s\n' "$0" "$msg" >&2
exit 1
}
# Do a random shuffle of the 'dirs' array
# (Code adapted from "BashFAQ/026 - Greg's Wiki",
# <https://mywiki.wooledge.org/BashFAQ/026>)
function shuffle_dirs
{
local i tmp size max rand
size=${#dirs[@]}
for ((i=size-1; i>0; i--)); do
# RANDOM % (i+1) is biased because of the limited range of $RANDOM
# Compensate by using a range which is a multiple of the rand modulus.
max=$(( 32768 / (i+1) * (i+1) ))
while (( (rand=RANDOM) >= max )); do :; done
rand=$(( rand % (i+1) ))
tmp=${dirs[i]} dirs[i]=${dirs[rand]} dirs[rand]=$tmp
done
return 0
}
# Copy an FA/..._L/... directory and directories paired with it under $srcdir
# to a "split" directory ('test', 'train', or 'validation') under $destdir
function copy_dirs
{
local -r splitdir=$1 # 'test', 'train', or 'validation'
local -r fa_l_dir=$2 # E.g. 'FA/CN/CN_L/GE_FSPGR/b'
local -a parts
local p0 p2 path
IFS=/ read -r -a parts <<<"$fa_l_dir"
for p0 in FA T1; do
for p2 in "${parts[2]}" "${parts[2]%_L}_R"; do
path="$p0/${parts[1]}/$p2/${parts[3]}/${parts[4]}"
srcpath="$srcdir/$path"
destpath="$destdir/$splitdir/$path"
mkdir --parents --verbose -- "${destpath%/*}"
cp --archive --verbose -- "$srcpath" "$destpath"
done
done
return 0
}
#### "main"
if (( $# != 2 )); then
printf 'usage: %s SRCDIR DESTDIR\n' "$0" >&2
exit 1
fi
declare -r srcdir=$1
declare -r destdir=$2
# Check for existence of required directories
for d in "$srcdir" "$srcdir/FA" "$srcdir/T1" "$destdir"; do
[[ -e $d ]] || quit "'$d' does not exist"
[[ -d $d ]] || quit "'$d' is not a directory"
done
shopt -s nullglob
for groupdir in "$srcdir"/FA/*/*_L/*/; do
# Get the list of FA/..._L/group/... directories to be copied
dirs=()
for d in "$groupdir"*; do
dirs+=( "${d#"$srcdir/"}" )
done
ndirs=${#dirs[*]}
if (( ndirs == 0 )); then
printf "%s: WARNING: no directories match '$groupdir*'\\n" "$0" >&2
continue
fi
# Randomly shuffle the list of directories to randomize which directories
# get copied to which locations
shuffle_dirs
declare -i pc_sum=0 lo=0 hi
for splitdir_pc in test:60 train:20 validation:20; do
splitdir=${splitdir_pc%:*}
pc=${splitdir_pc#*:}
pc_sum+=$pc
hi='(ndirs * pc_sum + 50)/100 - 1'
for ((i=lo; i<=hi; i++)); do
copy_dirs "$splitdir" "${dirs[i]}"
done
lo='hi+1'
done
done
exit 0
- 이 프로그램은 두 가지 명령줄 매개변수를 사용합니다.
FA
및 디렉토리가 포함된 디렉토리의 경로입니다T1
.test
train
, 및 디렉토리 가 포함된 디렉토리validation
(및 해당 디렉토리가 복사될 디렉토리)의 경로입니다.
- 관심이 있으시면 코드에 문서를 추가하거나 질문에 답변해 드리겠습니다.
답변2
경로 이름이나 파일 내용의 해시를 계산합니다. 다음은 해시 함수의 예입니다.
$ date | shasum
7ae62fd4e6483c966fd23d8eeafabc934226914d -
첫 번째 문자를 가져옵니다.... shasum | cut -c1
대략적으로 필요한 백분율에 해당하는 16개의 기호 링크를 만듭니다. 세 개의 기존 디렉터리를 가리킵니다.
ln -s /data/test 0
...
ln -s /data/test 9
ln -s /data/train a
ln -s /data/train b
ln -s /data/train c
ln -s /data/validate d
ln -s /data/validate e
ln -s /data/validate f
이제는 쉽습니다. 해시의 초기 문자와 cp
대상 디렉터리의 src 파일을 가져옵니다.
각 카테고리에서 대략적인 정확한 수의 파일을 얻을 수 있습니다. 1/16보다 1/256의 해상도를 선호하는 경우 각 해시의 처음 두 문자에 대한 기호 링크를 자유롭게 생성하세요.
편집하다
당신은 많은 파일을 가지고 있다고 말합니다.
FA/CN/CN_L/GE_FSPGR/a/one.csv
FA/CN/CN_L/GE_FSPGR/a/two.csv
...
FA/CN/CN_L/GE_FSPGR/a/one_hundred.csv
각 파일에 대해 훈련, 테스트, 검증의 세 가지 조건 중 하나를 선택하려고 합니다.
해시하자특별한경로명:
$ echo FA/CN/CN_L/GE_FSPGR/a/one.csv | shasum
16930ea7216d650735ea7c223a67371c5a5ed770 -
$
$ echo FA/CN/CN_L/GE_FSPGR/a/one.csv | shasum | cut -c1
1
다른 파일에 대해 이 작업을 반복하면 d
및 가 생성됩니다 2
.
"테스트" 영역으로 연결되어 해당 영역에 도달하고 $ cp one.csv 1
검증 데이터의 일부가 되는 여러 심볼릭 링크가 설정되었습니다 .$ cp one_hundred.csv 2
$ cp two.csv d