파일을 복사하고 파일 이름에 경로를 추가하세요.

파일을 복사하고 파일 이름에 경로를 추가하세요.

mp3 파일을 디렉토리에서 플래시 드라이브로 복사하고 싶습니다. 이는 다음 디렉토리 구조에 저장됩니다: Artist/Album/Track.mp3. 내 자동차의 mp3 플레이어가 형편없기 때문에 플래시 드라이브의 루트 디렉토리에 파일 이름이 Artist-Album-Track.mp3.

답변1

for매개변수 확장을 통해 다양한 요소를 추출하는 간단한 루프가 이를 수행합니다.

for file in */*/*.mp3;
do
  artist=${file%%/*}
  rest=${file#*/}
  album=${rest%%/*}
  track=${rest#*/*}
  cp -- "$file" /flash/drive/"${artist}-${album}-${track}"
done

첫 번째 확장은 파일 끝부터 첫 번째 슬래시(생성된 아티스트)까지 모든 것을 제거합니다.

두 번째 확장팩이 제거되었습니다.선두첫 번째 슬래시까지의 문자 - 경로에서 아티스트를 제거합니다.

세 번째 확장은 첫 번째 확장과 유사하며, 나머지 경로에서 파일 이름을 제거하고 앨범을 떠납니다.

네 번째 확장팩은 두 번째 확장팩과 유사하며, 앨범을 제거하고 파일 이름만 남깁니다.

그런 다음 이를 모두 함께 대시하고 원하는 /flash/drive 경로에 연결합니다.

답변2

다음 위치 에서 파일 사용 find및 복사 :bash$mp3dir$destdir

mp3dir="$HOME/my_music"
destdir="/mnt/my_mp3_player"

find "$mp3dir" -type f -name '*.mp3' -exec bash -c '
    mp3dir=$1; destdir=$2; shift 2
    for pathname do
        dest=${pathname#$mp3dir/}
        dest="$destdir/${dest//\//-}"
        if [ -f "$dest" ]; then
            printf "%s exist, skipping %s\n" "$dest" "$pathname" >&2
        else
            cp "$pathname" "$dest"
        fi
    done' bash "$mp3dir" "$destdir" {} +

$mp3dir로 시작하는 이름을 찾습니다 .mp3. 이러한 배치의 경우 짧은 스크립트가 실행됩니다. 이 스크립트의 두 매개 변수는 $mp3dir$destdir나머지 매개 변수는 MP3 파일의 경로 이름입니다.

스크립트는 처음 두 개의 명령줄 인수에서 두 개의 디렉터리 이름을 선택한 다음 나머지 인수를 반복하여 $dest각 MP3 파일의 대상 경로 이름을 만듭니다. 이는 bash경로 이름의 초기 비트를 제거한 후 경로 이름의 모든 슬래시를 대시로 바꾸는 매개변수 대체를 사용하여 수행됩니다 .$mp3dir

이미 존재하는 경우 $dest이 파일에 대한 메시지가 인쇄되고, 그렇지 않으면 복사됩니다.

관련된:

답변3

조작은 나쁜 습관이라고 생각해요여러 문자열쉘 매개변수 확장 및 변수 할당이 있습니다.

root_dir="~/songs"
for fn in */*/*.mp3  
do 
   cp -v "$fn" "${root_dir}/${fn////-}"    # replace all slashes by dashes
done

산출:

~/songs/Artist-Album-Track.mp3

답변4

배경

두 가지 목표를 달성하는 솔루션을 공식화하는 것이 가능한지 궁금합니다.

  • 읽기가 더 쉽다
  • 디버그하기가 더 쉽다

다음 제목의 다른 U&L Q&A에 대한 @kusalananda의 훌륭한 답변을 기반으로 합니다.-exec 옵션 이해find, 내 생각엔 당신의 문제를 해결할 방법을 알아낸 것 같아요.

첫째, 내 예제 디렉터리 구조는 여러분의 디렉터리 구조를 모방합니다.

$ mkdir -p Artist{1..5}/Album{1..5}
$ touch Artist{1..5}/Album{1..5}/Track{1..5}.mp3

결과는 다음과 같습니다.

$ find Artist* -type f | head
Artist1/Album1/Track1.mp3
Artist1/Album1/Track2.mp3
Artist1/Album1/Track3.mp3
Artist1/Album1/Track4.mp3
Artist1/Album1/Track5.mp3
Artist1/Album2/Track1.mp3
Artist1/Album2/Track2.mp3
Artist1/Album2/Track3.mp3
Artist1/Album2/Track4.mp3
Artist1/Album2/Track5.mp3

이제 mp3 파일을 다음 위치에 복사하세요 ./targetDir.

$ find . -type f -name '*.mp3' -exec sh -c \
    'cp {} targetDir/$(echo "{}" | sed "s#\./##g;s#/#-#g")' \;

결과는 다음과 같습니다.

$ ls targetDir/ | head
Artist1-Album1-Track1.mp3
Artist1-Album1-Track2.mp3
Artist1-Album1-Track3.mp3
Artist1-Album1-Track4.mp3
Artist1-Album1-Track5.mp3
Artist1-Album2-Track1.mp3
Artist1-Album2-Track2.mp3
Artist1-Album2-Track3.mp3
Artist1-Album2-Track4.mp3
Artist1-Album2-Track5.mp3

cp ...나는 명령을 먼저 래핑 하여 echo작업을 제출하기 전에 출력을 확인할 수 있기 때문에 이 접근 방식을 좋아합니다 .

$ find . -type f -name '*.mp3' -exec sh -c \
    'echo "cp {} targetDir/$(echo "{}" | sed "s#\./##g;s#/#-#g")"' \;
cp ./Artist1/Album1/Track1.mp3 targetDir/Artist1-Album1-Track1.mp3
cp ./Artist1/Album1/Track2.mp3 targetDir/Artist1-Album1-Track2.mp3
cp ./Artist1/Album1/Track3.mp3 targetDir/Artist1-Album1-Track3.mp3
cp ./Artist1/Album1/Track4.mp3 targetDir/Artist1-Album1-Track4.mp3
cp ./Artist1/Album1/Track5.mp3 targetDir/Artist1-Album1-Track5.mp3
cp ./Artist1/Album2/Track1.mp3 targetDir/Artist1-Album2-Track1.mp3
cp ./Artist1/Album2/Track2.mp3 targetDir/Artist1-Album2-Track2.mp3
cp ./Artist1/Album2/Track3.mp3 targetDir/Artist1-Album2-Track3.mp3
cp ./Artist1/Album2/Track4.mp3 targetDir/Artist1-Album2-Track4.mp3
...

어떻게 작동하나요?

솔루션은 다음 셸 명령의 출력을 가져온 find후 실행됩니다.

cp {} targetDir/$(echo "{}" | sed "s#\./##g;s#/#-#g")'

cp이렇게 하면 파일이 에서 Artist../Album../Track..로 변경되고 targetDir/..이름이 다시 작성되어 -슬래시( )가 있는 곳에 대시( )가 있게 됩니다 /.

노트:대신 사용할 경우 존재할 수 있는 접두사를 sed먼저 제거하는 것이 좋습니다 ../find . ...find Artist* ..

대안?

나는 이것을 사용 find하고 수행하는 것이 cp여전히 이상적인 솔루션이 아니라고 생각합니다. 나는 또한 MP3 파일의 디렉토리를 관리하고 있으며 rsync제공한 목록을 통해 비슷한 작업을 수행하는 것이 rsync실행할 때마다 다시 복사하는 대신 업데이트하는 데 사용할 수 있으므로 장기적으로 더 유용한 구현이 될 수 있다고 생각합니다.

$ man rsync
...
        --files-from=FILE       read list of source-file names from FILE

그냥 생각입니다.

관련 정보