【问题标题】:Bash Shell file convert .sass ans .scss into cssBash Shell 文件将 .sass 和 .scss 转换为 css
【发布时间】:2020-12-15 01:11:10
【问题描述】:

我正在尝试构建一个 sass 工作区。

我 - 目标

我有两个目录:

  • 一个是包含 .sass 或 .scss 文件的 SASS 目录,
  • 一个是包含 .css 文件的 CSS 目录。

/css 是/sass 文件转换结果的目标目录。

我的目标是在 /sass 目录中编写 sass 或 scss 代码,并调用 bash 文件将 /sass 中的每个 .sass 或 .scss 文件转换为 /css 目录中的 .css 结果。

II - 我做了什么:

[/!\ 可能没看全,先到第三部分解释问题]

这是我的 /convert bash 文件:

SASS_FILES_PATH=sass
CSS_DEST_PATH=css

function get_cleaned_filename {
        # Split fileName to removre file directory:
        IFS='/' # Split delimiter
        read -ra ADDR <<< "$1"
        local ARRAY_LENGTH=${#ADDR[@]}
        RESULT="${ADDR[$ARRAY_LENGTH - 1]}"

        # Split fileName to removre file type:
        IFS='.' # Split delimiter
        read -ra ADDR <<< "$RESULT"
        RESULT="${ADDR[0]}"
}

# function convert_file/1 convert the file in parameter into .css file
# Parameters : $1 : path to source file
# Precondition : file in parameter should have .scss ou .sass extension
#               
# Postcondition : create a .css and a .css.map files that correspond to
#   the converted .sass or .scss file.
function convert_file {
        get_cleaned_filename $f;
        FILENAME=$RESULT;

        #   We can have two files .sass and .scss using the same name :
        if test -f $CSS_DEST_PATH/$FILENAME.css;
        then
            echo "a file $CSS_DEST_PATH/$FILENAME.css exist";
            FILENAME=$FILENAME_2;
            echo "renamed to $FILENAME_2";
        fi
        
        echo "[DEBUG]: sass ${f} ${CSS_DEST_PATH}/${FILENAME}.css";
        sass --trace ${f} ${CSS_DEST_PATH}/${FILENAME}.css;
}

if ! test -f $SASS_FILES_PATH/*.sass || ! test -f $SASS_FILES_PATH/*.scss;
then
    echo "Pas de fichier à convertir dans le dossier, aucune opération n'a été éxécutée.";
else 
    #   Empty CSS_DEST_PATH :
    if test -f $CSS_DEST_PATH/*;
    then 
        for cssFileName in $CSS_DEST_PATH/*;
        do
            rm $cssFileName;
        done
    fi

    #   Convert every .scss and .sass files into .css

    #   If scss file exist in curent directory
    if test -f $SASS_FILES_PATH/*.scss;
    then
        #   Convert each .scss file into css and move it to css directory
        for f in $SASS_FILES_PATH/*.scss;
        do 
            convert_file $f;
        done
    fi

    #   If sass file exist in curent directory
    if test -f $SASS_FILES_PATH/*.sass;
    then
        #   Convert each .sass file into css and move it to css directory
        for f in $SASS_FILES_PATH/*.sass;
        do 
            convert_file $f;
        done
    fi
fi

III - 错误是什么:

在函数 convert_file\1 中,我有一个错误:

        echo "[DEBUG]: sass ${f} ${CSS_DEST_PATH}/${FILENAME}.css";
        sass --trace ${f} ${CSS_DEST_PATH}/${FILENAME}.css;

sass 调用(第二行)返回错误:

me@myComputer:~/Desktop/computing/sassWorkshop$ bash convert
[DEBUG]: sass sass/test.scss css/test.css
Traceback (most recent call last):
    7: from /usr/bin/sass:8:in `<main>'
    6: from /usr/lib/ruby/vendor_ruby/sass/exec/base.rb:19:in `parse!'
    5: from /usr/lib/ruby/vendor_ruby/sass/exec/base.rb:52:in `parse'
    4: from /usr/lib/ruby/vendor_ruby/sass/exec/sass_scss.rb:52:in `process_result'
    3: from /usr/lib/ruby/vendor_ruby/sass/exec/base.rb:120:in `process_result'
    2: from /usr/lib/ruby/vendor_ruby/sass/exec/base.rb:182:in `open_file'
    1: from /usr/lib/ruby/vendor_ruby/sass/exec/base.rb:182:in `open'
/usr/lib/ruby/vendor_ruby/sass/exec/base.rb:182:in `initialize': No such file or directory @rb_sysopen - sass/test (Errno::ENOENT)

请注意,“convert”是我使用的 bash 文件的名称!

我不明白的是,我的 echo "[DEBUG]: ..." 行打印出根据我的变量,sass 调用是 "sass sass/test.scss css/test.css"。但是当我在终端中输入这一行时,该行运行良好,并且我的 .css 文件已创建。

IV - 我尝试了什么:

我尝试了“rm .sass-cache/ -R”,它没有改变任何东西。

如果我的帖子格式不正确,或者有很多英文错误(不是我的妈妈丁字裤),我很抱歉,如果是这种情况,请告诉我 :)

感谢任何可以帮助我的评论

【问题讨论】:

  • 切线,不要对私有变量使用大写;全大写名称保留给系统变量。
  • @HedwinBonnavaoud : 你的sass 目录中的某些文件是否具有嵌入空格的名称?
  • 感谢@tripleee 的提示,我会注意的。
  • no @user1934428 我没有空格,每个文件名都像something_somthingelse.sass whout caps,除了'_'之外没有其他字符。
  • 在这种情况下,我们唯一知道的是 Ruby 尝试打开 sass/test,我们知道它不存在,它必须从某个地方获取这个名称,很可能来自命令参数.您是否尝试在-x 下运行它,看看这里到底发生了什么?

标签: bash shell sass


【解决方案1】:

你真的应该用 shellcheck.net 检查你的脚本,因为它包含几个错误,主要是由于变量周围缺少双引号、使用了不推荐使用的测试以及我无法解释的一些事情:

FILENAME=$FILENAME_2;

变量FILENAME_2的值没有设置。

还有: if ! test -f $SASS_FILES_PATH/*.sass || ! test -f $SASS_FILES_PATH/*.scss;

-f 不适用于 glob,因此您需要迭代每个 glob 以更新标志并测试每个标志,或者更好地使用 find 命令返回码

if ! find "$SASS_FILES_PATH/" -name '*.sass' || ! find "$SASS_FILES_PATH/" -name '*.scss'

无用且危险的不安全rm循环:

        for cssFileName in $CSS_DEST_PATH/*;
        do
            rm $cssFileName;
        done

替换为

        rm -- "$CSS_DEST_PATH/"*

同样的问题,无法使用 globbing 测试 -f

    #   If scss file exist in curent directory
    if test -f $SASS_FILES_PATH/*.scss;

这将测试文件是否存在并在每个条目上执行转换:

    find "$SASS_FILES_PATH" -name '*.scss" -o -name '*.sass' -exec convert {} \;

您清理文件名的功能不是最理想的:

function get_cleaned_filename {
        # Split fileName to removre file directory:
        IFS='/' # Split delimiter
        read -ra ADDR <<< "$1"
        local ARRAY_LENGTH=${#ADDR[@]}
        RESULT="${ADDR[$ARRAY_LENGTH - 1]}"

        # Split fileName to removre file type:
        IFS='.' # Split delimiter
        read -ra ADDR <<< "$RESULT"
        RESULT="${ADDR[0]}"
}

改为:

function get_cleaned_filename {
        filename="${1##*/}"    # remove leading directories path
        echo "${filename%\.*}" # remove dot suffix
}

然后在convert_file:

function convert_file {
        FILENAME="$(get_cleaned_filename "$1")";

最后,这可能会做你想做的事:

find sass/ -type f \( -name '*.scss' -o -name '*.sass' \) -exec bash -c 'src="$0"; _tdest="/${0%\.*}"; dest="css/${_tdest##*/}.css"; rm -f "$dest"; sass --trace "$src" "$dest"' {} \;

#!/usr/bin/env bash

find sass/ -type f \( -name '*.scss' -o -name '*.sass' \) -exec bash -c '
  # Source file (.scss or .sass) passed as argument 0
  src="$0" 

  # Strip-out file name extension
  _tdest="/${0%\.*}"

  # Construct destination file path/name.css
  dest="css/${_tdest##*/}.css" # Construct destination file path/name.css

  # Remove destination file if it exists
  rm -f "$dest"

  # Perform the scss|sass compilation
  sass --trace "$src" "$dest"
' {} \;

【讨论】:

  • 好的,所有这些提示都非常有用,我会检查一下,但是关于“FILENAME=$FILENAME_2;”,我的意思是“在 $FILENAME 末尾添加 '_2'”,但可能类似于“FILENAME” =`${FILENAME}_2" 更好?
  • 是的,需要大括号来保留下划线。