Eu decidi ganhar alguma experiência com a Bash e escrevi o script abaixo, que tem os seguintes recursos:
- Ele pode manipular todos os arquivos e pastas, colocados no diretório atual.
- Se houver mais de uma legenda ou arquivo de vídeo (exceto arquivos de amostra), o script solicitará a interação manual.
- Em todos os outros casos, o script moverá automaticamente todos os arquivos e pastas para um diretório de backup ( tenha cuidado para executá-lo! ), que será movido para o diretório pasta de lixo do usuário, em vez de ser excluída.
- Ele pode lidar com vários tipos de extensões de vídeo e legendas.
- Ele usa
mkvmerge
para mesclar vídeo com arquivos de legenda e também usanotify-send
para mostrar algumas mensagens na GUI. Também usagvfs-trash
para mover arquivos na pasta de lixo do usuário. - Ele pode ser usado como script do Nautilus ou como script de shell regular, mas o ambiente do GIU é obrigatório, enquanto o comando
notify-send
existe no corpo do roteiro. - O nome do arquivo de saída pode ser baseado no nome do diretório (padrão) ou no nome do arquivo de vídeo de origem.
- Além disso, quando apenas dois arquivos são selecionados ( um arquivo de vídeo e um arquivo de legenda ), eles serão mesclados e o restante do conteúdo da pasta será retido . O arquivo de saída será nomeado após o arquivo de vídeo de origem. Esta opção está disponível somente quando o script é usado como script do Nautilus.
O script:
#!/bin/bash -e
# Check if all tools are available
[ -x /usr/bin/notify-send ] || (echo "Please, install 'notify-send'"; exit 1)
[ -x /usr/bin/mkvmerge ] || (echo "Please, install 'mkvmerge'"; exit 1)
# Allowed video and subtitle file extensions
EXT_VIDEO=("mp4 avi mpg mov mkv wmv")
EXT_SUB=("sub str srt vtt")
# Files, which names contains some of next strings will be removed in auto mode
FILTER=("sample Sample SAMPLE")
# Log file
MERGE_LOG="/tmp/merge-video-sub.log"
echo > "$MERGE_LOG"
#
# Functions
#
function get-video-and-sub-file-names {
# Get the names of the video and subtitle files and move the rest of the files into the Backup directory
for ((i=0; i<${#FILE_LIST[@]}; i++)); do
FILE_NAME="${FILE_LIST[$i]%.*}"
FILE_EXT="${FILE_LIST[$i]##*.}"
if [[ "${EXT_SUB[@]}" == *"$FILE_EXT"* ]]; then
SUB_FULL_FILE_NAME="${FILE_LIST[$i]}"
SUB_FILE_NAME="${FILE_NAME}"
SUB_FILE_EXT="${FILE_EXT}"
elif [[ "${EXT_VIDEO[@]}" == *"$FILE_EXT"* ]]; then
VIDEO_FULL_FILE_NAME="${FILE_LIST[$i]}"
VIDEO_FILE_NAME="${FILE_NAME}"
VIDEO_FILE_EXT="${FILE_EXT}"
else
# We need 'find' to manipulate only with files, because "$BACKUP_DIR" is in the queue
find ./* -maxdepth 0 -type f -name "${FILE_LIST[$i]}" -exec mv "{}" "$BACKUP_DIR" \; -exec echo -e "The file {} was REMOVED.\n" >> "$MERGE_LOG" \;
fi
done
}
function get-the-content-of-the-current-directory {
# Get the content of the current directory
shopt -s nullglob
FILE_LIST=(*)
shopt -u nullglob
}
function mkvmerge-video-and-sub-files {
# Create merged file
mkvmerge -o "$OUTPUT_FILE" "$VIDEO_FULL_FILE_NAME" "$SUB_FULL_FILE_NAME"
sleep 3
}
#
# Scenario 1: If exactly two files are selected in Nautilus! Then check if they are 1 video and 1 subtitle files, if yes - merge and remove them
# Scenario 2: Else run the standard procedure
#
# Get the files, selected in Nautilus as file list. Use next command to check the result: notify-send "MESSAGE" "'echo -e "${#FILE_LIST[@]}"; printf '%s\n' "${FILE_LIST[@]}"'"
IFS_BAK=$IFS
IFS=$'\t\n'
FILE_LIST=($NAUTILUS_SCRIPT_SELECTED_FILE_PATHS)
IFS=$IFS_BAK
if [ "${#FILE_LIST[@]}" -eq "2" ]
then # Scenario 1
# Get the names of the video and subtitle files
get-video-and-sub-file-names
if [[ "${EXT_SUB[@]}" == *" $SUB_FILE_EXT "* ]] && [[ "${EXT_VIDEO[@]}" == *" $VIDEO_FILE_EXT "* ]]
then
notify-send "OK" "'echo -e "The following files will be MERGED and MOVED to trash:"; printf '\t-\ %s\n' "${FILE_LIST[@]##*/}"'"
# Construct the name of the merged file.
OUTPUT_FILE="${VIDEO_FILE_NAME}.sub.mkv"
# Merge the files
mkvmerge-video-and-sub-files
# Move video and subtitle files into user's trash directory and create trash infofile
if [ -f "$OUTPUT_FILE" ]
then
gvfs-trash "$VIDEO_FULL_FILE_NAME"
gvfs-trash "$SUB_FULL_FILE_NAME"
notify-send "OK" "'echo -e "THE NAME OF THE NEW MERGED FILE IS:\n${OUTPUT_FILE##*/}"'"
else
notify-send "ERROR 1" "'echo "Something went wrong!"'"
fi
else
notify-send "ERROR" "'echo -e "\n\t\nTo use this function, please select exactly:\n\t- 1 video file and\n\t- 1 subtitle file!\n\t\nYou are selected these files:"; printf '\t-\ %s\n' "${FILE_LIST[@]##*/}"'"
fi
else # Scenario 2
# Get the current directory name
DIR_NAME="${PWD##*/}"
# Create Backup sub-directory
BACKUP_DIR="${DIR_NAME}.backup"
[ -d "${BACKUP_DIR}" ] || mkdir "$BACKUP_DIR" && echo "The directory $BACKUP_DIR was CREATED.\n" > "$MERGE_LOG"
# Move all sub-directories into the Backup directory
shopt -s dotglob
find ./* -maxdepth 0 -type d ! -name "*$BACKUP_DIR*" -prune -exec mv "{}" "$BACKUP_DIR" \; -exec echo "The directory {} was REMOVED.\n" >> "$MERGE_LOG" \;
shopt -u dotglob
# Move all files and folders, whose names contains a string, that exists in $FILTER[@]
for f in $FILTER; do
shopt -s dotglob
find ./* -maxdepth 0 ! -name "*$BACKUP_DIR*" -type f -name "*$f*" -exec mv "{}" "$BACKUP_DIR" \; -exec echo "The file {} was REMOVED.\n" >> "$MERGE_LOG" \;
shopt -u dotglob
done
# Get the entire content of the current directory
get-the-content-of-the-current-directory
# Get the names of the video and subtitle files and move the rest of the files into the Backup directory
get-video-and-sub-file-names
# Construct the name of the merged file. It could be based on the parent directory or on the video file name Make your choice and comment/uncomment next lines
#OUTPUT_FILE="${VIDEO_FILE_NAME}.sub.mkv"
OUTPUT_FILE="${DIR_NAME}.sub.mkv"
# Get the entire content of the current directory after the filtering
get-the-content-of-the-current-directory
echo -e "$(cat $MERGE_LOG)" && notify-send "OK" "'echo -e "$(cat $MERGE_LOG)"'" && echo > "$MERGE_LOG"
# Check the current structure of the directory
if [ "${#FILE_LIST[@]}" -ne "3" ]; then
echo "The content structure must consists of next 3 items:" > "$MERGE_LOG"
echo "\t- 1 movie file,\n\t- 1 subtitle file and\n\t- 1 backup directory." >> "$MERGE_LOG"
echo "\n\t\nThe current number of contained items is ${#FILE_LIST[@]}." >> "$MERGE_LOG" && echo >> "$MERGE_LOG"
echo "\n\t\nPLEASE RESOLVE THIS MANUALLY!" >> "$MERGE_LOG"
echo -e "$(cat $MERGE_LOG)" && notify-send "ERROR" "'echo -e "$(cat $MERGE_LOG)"'"
else
echo "The directory structure looks good, is contains ${#FILE_LIST[@]} items." > "$MERGE_LOG"
echo " - The source VIDEO file is: ${VIDEO_FULL_FILE_NAME::21}... .${VIDEO_FULL_FILE_NAME##*.}" >> "$MERGE_LOG"
echo " - The source SUB file is: ${SUB_FULL_FILE_NAME::25}... .${SUB_FULL_FILE_NAME##*.}" >> "$MERGE_LOG"
echo "They has been merged and removed!" | tr /a-z/ /A-Z/ >> "$MERGE_LOG"
# Merge the files
mkvmerge-video-and-sub-files
# Move video and subtitle files into the Backup directory
mv "$VIDEO_FULL_FILE_NAME" "$BACKUP_DIR"
mv "$SUB_FULL_FILE_NAME" "$BACKUP_DIR"
# Move the Backup directory to trash and create trash infofile
if [ -f "$OUTPUT_FILE" ]; then
gvfs-trash "$BACKUP_DIR"
echo "\n\t\nThe Backup directory has been MOVED to Trash!\n\t\n" >> "$MERGE_LOG"
echo "The name of the new merged file is:" | tr /a-z/ /A-Z/ >> "$MERGE_LOG"
echo "${OUTPUT_FILE##*/}" >> "$MERGE_LOG"
echo -e "$(cat $MERGE_LOG)" && notify-send "OK" "'echo -e "$(cat $MERGE_LOG)"'"
else
echo "Something went wrong!" && notify-send "ERROR 2" "'echo "Something went wrong!"'"
fi
fi
fi
rm "$MERGE_LOG"
exit 1
Configuração:
-
Crie um arquivo executável e cole o conteúdo acima. Vamos chamar esse arquivo
merge-video-sub
:touch merge-video-sub chmod +x merge-video-sub nano merge-video-sub
-
Copie (ou
ln -s
) este arquivo para a pasta~/.local/share/nautilus/scripts
para disponibilizá-lo como script do Nautilus para o usuário atual. -
No momento não consigo encontrar uma maneira de disponibilizá-lo para todo o sistema como script do Nautilus.
-
Copie o arquivo para
~/bin
(e adicioneexport PATH=$PATH:~/bin
na parte inferior de~/.bashrc
, se necessário) para disponibilizá-lo como comando shell para o usuário atual. -
Copie o arquivo em
/usr/local/bin
para disponibilizá-lo como todo o sistema de comando do shell. -
O caminho curto é para
curl
do script de meu PasteBin diretamente na pastanautilus/scripts
:curl https://pastebin.com/raw/HrLTibuR | sed -e 's/\r$//' > $HOME/.local/share/nautilus/scripts/merge-video-sub chmod +x $HOME/.local/share/nautilus/scripts/merge-video-sub
Demo:
A demonstração anterior