「F3.bam」という名前の複数のファイルを2段階のディレクトリにコピーしてから、コピーしてからサブディレクトリ名にファイル名を変更しようとしています。
たとえば、
/samples/mydata1/RUN1/ID_date/PCR2/TIME1/F3.bam
/samples/mydata2/RUN1/ID2_date4/PCR2/TIME7/F3.bam
/samples/mydataxxx/RUN1/IDxxx_datexxx/PCR2/TIMExxx/F3.bam
予想される結果:
1. まず、ファイルを前の 2 つのディレクトリにコピーします。
/samples/mydata1/RUN1/ID_date/F3.bam
/samples/mydata2/RUN1/ID2_date4/F3.bam
/samples/mydataxxx/RUN1/IDxxx_datexxx/F3.bam
2. 現在のサブディレクトリの名前に基づいてファイル名を変更します。
/samples/mydata1/RUN1/ID_date/ID_date_F3.bam
/samples/mydata2/RUN1/ID2_date4/ID2_date4_F3.bam
/samples/mydataxxx/RUN1/IDxxx_datexxx/IDxxx_datexxx_F3.bam
理想的にはbashループをお勧めします(Macで動作)。
ベストアンサー1
私のソリューションのTLDRバージョンは次のとおりです。プロセス置換とコマンドを使用して、コピーdirname
コマンドbasename
へのターゲットパスを構築できます。
より詳細な説明は以下の通りである。
Bashループを使用しておおよその目的を実行する(非常に詳細な)スクリプトは次のとおりです。
#!/bin/bash
# copy_and_rename.bash
#
# Copy multiple files 2 folders up and rename these files
# to contain their parent directory as a prefix.
#
# Set internal field separator to handle spaces in file names
IFS=$'\n'
# Iterate over the list of file paths
for _file_path in $@; do
# Get the file name
_file_name="$(basename ${_file_path})"
echo "${_file_name}"
# Get the path to the target directory (two levels above the file)
_target_directory_path=$(dirname $(dirname ${_file_path}))
echo "${_target_directory_path}"
# Get the parent directory of the target directory
_parent_directory_path=$(dirname ${_target_directory_path})
echo "${_parent_directory_path}"
# Get the name of the parent directory
_parent_directory_name=$(basename ${_parent_directory_path})
echo "${_parent_directory_name}"
# Construct the new file path
_new_file_path="${_target_directory_path}/${_parent_directory_name}_${_file_name}"
echo "${_new_file_path}"
# Copy and rename the file
echo "cp -i \"${_file_path}\" \"${_new_file_path}\""
cp -i "${_file_path}" "${_new_file_path}"
echo
done
もちろん、たくさん圧縮することもできますが、値を説明するためにこれを維持しました。
echo
コメントや関連のない変数やステートメントなしの前のスクリプトは次のとおりです。
for _file_path in $@; do
cp -i "${_file_path}" \
"$(dirname $(dirname ${_file_path}))/$(basename $(dirname $(dirname $(dirname ${_file_path}))))_$(basename ${_file_path})"
done
非常に壊れやすく、エラー処理の面で多くのことはしません。また、デバッグ用のステートメントをいくつか残しているecho
ため、初めて実行するときにデバッグが実行される操作を確認し、正しく機能していることを確認できます。
テストするために、次のスクリプトを使用してファイルを作成しました。追加のテストに役立つ場合に備えて、ここに含めました。
#!/bin/bash
# create_test_files.bash
# Set internal field separator to handle spaces in file names
IFS=$'\n'
# Choose an prefix for the file paths
_prefix="/tmp"
# Create array of sample files
_sample_files=(
"/samples/mydata1/RUN1/ID_date/PCR2/TIME1/F3.bam"
"/samples/mydata2/RUN1/ID2_date4/PCR2/TIME7/F3.bam"
"/samples/mydataxxx/RUN1/IDxxx_datexxx/PCR2/TIMExxx/F3.bam"
)
# Create directories and files
for _file in "${_sample_files[@]}"; do
# Add the prefix to the path
_path="${_prefix}${_file}"
# Create parent directory
mkdir -p "$(dirname ${_path})"
# Create file
touch "${_path}"
done
次のコマンドを使用して、ファイルが正しく作成されたことを確認しましたfind
。
$ find /tmp/samples -type f
/tmp/samples/mydata1/RUN1/ID_date/PCR2/TIME1/F3.bam
/tmp/samples/mydata2/RUN1/ID2_date4/PCR2/TIME7/F3.bam
/tmp/samples/mydataxxx/RUN1/IDxxx_datexxx/PCR2/TIMExxx/F3.bam
次にスクリプトを次のように呼び出します。
bash copy_and_rename.bash \
/tmp/samples/mydata1/RUN1/ID_date/PCR2/TIME1/F3.bam \
/tmp/samples/mydata2/RUN1/ID2_date4/PCR2/TIME7/F3.bam \
/tmp/samples/mydataxxx/RUN1/IDxxx_datexxx/PCR2/TIMExxx/F3.bam
次に、次を使用してスクリプトが再び機能することを確認しますfind
。
$ find /tmp/samples -type f
/tmp/samples/mydata1/RUN1/ID_date/PCR2/ID_date_F3.bam
/tmp/samples/mydata1/RUN1/ID_date/PCR2/TIME1/F3.bam
/tmp/samples/mydata2/RUN1/ID2_date4/PCR2/ID2_date4_F3.bam
/tmp/samples/mydata2/RUN1/ID2_date4/PCR2/TIME7/F3.bam
/tmp/samples/mydataxxx/RUN1/IDxxx_datexxx/PCR2/IDxxx_datexxx_F3.bam
/tmp/samples/mydataxxx/RUN1/IDxxx_datexxx/PCR2/TIMExxx/F3.bam
最後に、以下を使用してすべてのテストファイルを削除しましたfind
。
find /tmp/samples -type f -exec rm {} \;