여러 디렉터리의 파일 정렬 및 복사

여러 디렉터리의 파일 정렬 및 복사

파일이 포함된 여러 하위 디렉터리가 있는 디렉터리가 있습니다.

각 디렉토리의 파일을 이름별로 알파벳순으로 정렬하고 각 디렉토리의 첫 번째 파일을 지정된 새 디렉토리에 복사하고 싶습니다.

  • 숨겨진 파일을 무시하고 싶습니다.
  • 대상 디렉터리에 같은 이름의 파일이 있으면 두 파일을 모두 보존해야 합니다.

견본:

parentdir
->dir1
    ->afile
    ->bfile
    ->cfile
->dir2
    ->dfile
    ->efile
    ->ffile
->dir3
    ->afile
    ->hfile
    ->ifile

다음과 같이 새 디렉터리를 채우는 명령을 실행하고 싶습니다.

newdir
->afile
->afile.1
->dfile

이것이 어떻게 달성될 수 있습니까?

답변1

가장 쉬운 방법은 복사 대상을 사용하여 ls파일을 나열 하는 것입니다 . head이 bash 스크립트에 표시된 대로:

for d in ./*/; do
    src="$(ls "$d" | head -n 1)"
    dstbase="newdir/$(basename "$src")"
    if [[ ! -f "$dstbase" ]]; then
        cp "$src" "$dstbase"
    else
        suffix=1
        while [[ -f "$dstbase.$suffix" ]]; do
            let suffix++
        done
        cp "$src" "$dstbase.$suffix"
    fi
done

당연히 그에 따라 파일 경로를 조정해야 합니다. 복사할 때 등 아래의 디렉터리를 제외하려는 경우 dir1문제가 발생할 수 있으므로 이는 매우 취약합니다. dir2또한 사용되지 않은 파일 이름을 찾는 루프에 잠재적인 경쟁 조건이 있습니다. 이는 아마도 문제가 되지 않을 것이지만 여러 복사본을 병렬로 실행하는 것과 같은 작업은 수행하지 마십시오.

답변2

이는 다음 줄을 사용하여 달성할 수 있습니다.

ls -ltr /parent_directory_path/ |
awk '$1~"^drw" {print $9}' |
while read line; do
  ls -l $line |
  awk '$1 ~ "^-r" {print $9}' |
  head -1 |
  awk -v line="$line" '{print "cp -rvfp"  "  " line"/"$1 " " "/newdir/" }';
done |
sh

답변3

zshGNU를 사용하면 cp:

cd parentdir &&
  for dir (*(/)) (cp --backup=numbered -- $dir/*(.[1]) newdir/)

--backup=numbered파일 이름이 지정되는 백업 구성표를 구현했습니다 file.~1~. file.~2~... 따라서 첫 번째 복사본이 마지막 복사본이 됩니다 file.~max~(순서를 바꾸려면 file목록을 거꾸로 처리( *(/On)대신)).*(/)

POSIXly에서는 다음과 같이 할 수 있습니다.

cp_numbered() (
  suffix=
  n=0
  while [ -e "$2$suffix" ] || [ -L "$2$suffix" ]; do
    suffix=.$((n += 1))
  done
  exec cp -- "$1" "$2$suffix"
)
cd parentdir &&
  for dir in */; do
    for file in "$dir"/*; do
      if [ -f "$file" ]; then
        cp_numbered "$file" "newdir/${file#*/}"
        continue 2
      fi
    done
  done

관련 정보